zoukankan      html  css  js  c++  java
  • JDBC和分包

    JDBC(Java Data Base Connectivity,java数据库连接)

    JDBC是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范。

    JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

    JDBC需要连接驱动(就是实现类),由数据库厂商提供。

    1 JDBC原理

    是面向接口编程

    Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。

     

    JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库。

    2 JDBC开发步骤

    1)导驱动包

    项目上new一个文件夹lib(右键--new--Folder--输入lib),把驱动包(下载下来的,如下图)

     

    把这个文件复制进lib中,右键--build path--add to build path,可以看到项目多了一些文件

     

    每个项目这样导一次就可以。

    2)注册驱动

    代码为:Class.forName("com.mysql.jdbc.Driver");

    意思是将Driver类加载到内存,让其运行。

    Driver类就在刚才导入的驱动包中:

     

    写完后会有异常,因为传参数是字符串,出错可能性大(一般按格式传字符串的,都会抛异常)。

     

    这里可以先throws,实际做项目时,再try/catch。

    还有另一种注册方法,但不推荐

     

    3)获取连接

    代码:Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);

    三个参数分别表示:

    url 需要连接数据库的位置(网址)

    user用户名  

    password 密码

    JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔。

    第一部分是jdbc,这是固定的;

    第二部分是数据库名称,连接mysql数据库,当然就写mysql;

    第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求。

    mysql的第三部分分别由数据库服务器的IP地址(localhost)、端口号(3306),以及DATABASE数据库名称(mydb)组成。

    这里有可能连接不成功,所以还要thorws异常

     

    4)获得语句执行平台

    格式:

    获取Statement语句执行平台:Statement sta = con.createStatement();

    注意导包要导sql下的

     

    String sql = "某SQL语句";

    常用方法为:

    int executeUpdate(String sql); --执行insert update delete语句,(增,删,改都用这个)

    ResultSet executeQuery(String sql); --执行select语句(查询用这个)

    5)处理结果集(只查询时需要)

    ResultSet实际上就是一张二维的表格,可以调用其boolean next()方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1开始)来获取指定列的数据:

    rs.next();//指向第一行

    rs.getInt(1);//获取第一行第一列的数据

    常用方法:

    Object getObject(int index) / Object getObject(String name) 获得任意对象

    String getString(int index) / Object getObject(String name) 获得字符串

    int getInt(int index) / Object getObject(String name) 获得整形

    double getDouble(int index) / Object getObject(String name) 获得双精度浮点型

    也就是数据库中的字段是什么类型的,就用相应的类型的方法来获取。

    6)释放资源

    原则是先开后关。

    rs.close();

    stmt.close();

    con.close();

    例:

    首先建一个数据库market0929,再建一个user表

    插入一条数据

      

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class Test1 {
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		//注册驱动
    		Class.forName("com.mysql.jdbc.Driver");
    		//获得连接对象
    		String url="jdbc:mysql://127.0.0.1:3306/market0929?useUnicode=true&characterEncoding=UTF-8";
    		String user="root";
    		String password="123456";		
    		Connection conn=DriverManager.getConnection(url, user, password);
    		//获取语句执行平台
    		Statement sta=conn.createStatement();
    		
    		//让用户输入用户名和密码
    		Scanner sc=new Scanner(System.in);
    		System.out.println("请输入用户名:");
    		String uname=sc.next();
    		System.out.println("请输入密码:");
    		String pwd=sc.next();		
    		
    		//执行sql
    		String sql="select count(*) from user where uname='"+uname+"' and password='"+pwd+"'";
    		
    		//处理结果集
    		ResultSet rs=sta.executeQuery(sql);		
    		int count=0;
    		while(rs.next()){
    			count=rs.getInt(1);//取第一列
    		} 
    		System.out.println(count);
    		
    		//释放 先开后关
    		rs.close();
    		sta.close();
    		conn.close();
    	}
    }
    

     

    Tips:

    1)返回1,说明登录成功。

    2)里面?useUnicode=true&characterEncoding=UTF-8"; 这样写是为了和数据库的字符集统一,避免添加数据时全是乱码。

    3)字符串拼接技巧:先写两个双引,在里面写两个加号,再在加号里面写上变量

    3 SQL注入问题

    上面那个登录的例子,如果这样输入:

     

    可以看到,返回了1,说明登录成功了。

    因为这样输入时,实际的sql为:

    SELECT COUNT(*) FROM USER WHERE uname='suiyishu' AND PASSWORD='1' OR '1=1';

      

    这条查询语句永远可以查询出结果,那么用户就直接登录成功了,这便是SQL注入问题。

    4预处理对象

    为了解决SQL注入问题,使用PreparedStatement预处理对象。

    每条sql语句所有的实际参数都先用?占位,参数使用逗号分隔,然后再给?赋值。这样保证sql语句的结构不会再变了,不管用户输入什么,都被认为是值。

    4.1格式:

    String sql = "insert into sort(sid,sname) values(?,?)";

    PreparedStatement psmt = conn.prepareStatement(sql);

    4.2设置实际参数

    void setXxx(int index, Xxx xx) 将指定参数设置为给定Javaxx值。

    4.3常用方法:

    PreparedStatement是继承Statement的,所以其方法都一样:

    增删改用:int executeUpdate();

    查询用:ResultSet executeQuery();

    查询的还要处理结果集,都是一样的。就只是执行sql时不同,以后都用PreparedStatement来写。

    5 JDBC工具类

    “获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class JDBCUtils {
    	//工具类
    	public static Connection getConn(){
    		Connection conn=null; //定义成成员变量
    		try {
    			//注册驱动
    			Class.forName("com.mysql.jdbc.Driver");
    			//获得连接对象
    			String url="jdbc:mysql://127.0.0.1:3306/market0929?useUnicode=true&characterEncoding=UTF-8";
    			String user="root";
    			String password="123456";		
    			conn=DriverManager.getConnection(url, user, password);
    		} catch (ClassNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return conn;
    	}
    	
    	//释放增删改资源
    	public static void close(Connection conn,PreparedStatement pst){		
    		if(pst!=null){
    			try {
    				pst.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}		
    		if(conn!=null){
    			try {
    				conn.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	//释放查询资源
    	public static void close(Connection conn,PreparedStatement pst,ResultSet rs){
    		if(rs!=null){
    			try {
    				rs.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		if(pst!=null){
    			try {
    				pst.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		if(conn!=null){
    			try {
    				conn.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}	
    }
    

    6上面登录的例子修改为:

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class Test3 {
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		//让用户输入用户名和密码
    		Scanner sc=new Scanner(System.in);
    		System.out.println("请输入用户名:");
    		String uname=sc.next();
    		System.out.println("请输入密码:");
    		String pwd=sc.next();	
    		
    		//获取连接对象
    		Connection conn=JDBCUtils.getConn();		
    		
    		//获取语句执行平台
    		String sql="select count(*) from user where uname=? and password=?";
    		PreparedStatement pst=conn.prepareStatement(sql); //注意导sql包   是Statement子类
    		
    		//给问号赋值
    		pst.setString(1, uname);
    		pst.setString(2, pwd);
    		
    		//执行sql
    		ResultSet rs=pst.executeQuery();
    		
    		//处理结果集		
    		int count=0;
    		while(rs.next()){
    			count=rs.getInt(1);//取第一列
    		} 
    		System.out.println(count);
    		
    		//释放资源
    		JDBCUtils.close(conn,pst,rs);
    	}
    }
    

    再输入一下:

     

    7项目分层(分包)

    • view层作用: 视图层,即项目中的界面
    • controller层作用: 控制层, 获取界面上的数据,为界面设置数据; 将要实现的功能交给业务层处理。连接前后端的类,接收前台封装 和页面
    • service层作用: 业务层, 功能的实现, 与controller控制层和数据访问层DAO交互, 将对数据库的操作交给DAO数据访问层来处理
    • dao层(Data Access Object))作用: 数据访问层, 用来操作数据库表的数据
    • db数据库: 这里指MySQL
    • domain 实体包: 存放JavaBean
    • tools工具包:存放项目中使用到的工具类
    • test 测试包: 存放项目功能测试的代码 

    Tips:

    1)用参数列表 返回值,一层调一层

    2)View层:只有ScannerSystem.out.println,(及一些简单的处理, 正则表达式,验证用户输入等,相当于js)

    3)Controller层:用于封装数据

    4)Service层:处理业务逻辑

    5)Dao:与数据库有关的所有。一个类对应一个表

    6)一般在dao层throws异常。在Servicetry/catch 

    例:

    建一个商品分类表:sort

     

    项目结构为:

     

    (方便复制

    test

    view

    tools

    domain

    controller

    service

    dao

    实现步骤:

    1)写view,建一个run方法创建Controller层对象,在该调用Controller层方法的地方先加好注释

    2)建实体类,成员变量就是数据库中的字段名,点出get,set方法和toString方法

    3)tools中放工具类

    4)写dao层

    5)写Service层,创建dao层对象调用dao层方法

    6)写Controller层,创建Service层对象调用Service层方法,如果view层传的参数过多,可以封装成一个对象,再向后传

    7)回到view调用Controller层方法

    8)test层中写main方法,调用view层的run方法

    实例代码下载:

  • 相关阅读:
    动画02
    动画01
    css过渡
    06强制类型转换
    05强制类型转换
    jetson 安装opencv4.4.0
    cpp中的内置异常
    cpp中std::string和std::wstring 相互转换
    qt creator杂记
    win10 git bash 使用vim 显示 git log
  • 原文地址:https://www.cnblogs.com/hzhjxx/p/10123248.html
Copyright © 2011-2022 走看看