提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
JDBC回顾
- 前言
 - 一、JDBC
 - 1.JDBC是什么?
 - 2.如何使用?
 - (1)注册驱动
 - (2)获取连接
 - (3)操作数据表
 
- 3、ResultSet与ResultSetMetaData
 - (1)ResultSet
 - (2)ResultSetMetaData
 
前言
前段时间看到有关JDBC的一篇文章,颇有感触,闲来无事回顾总结一下有关JDBC的知识点。
提示:以下是本篇文章正文内容,下面案例可供参考
一、JDBC
1.JDBC是什么?
我们在未使用JDBC之前,连接不同的数据库,就像如下图例一样,使用那个数据库就使用对应的连接方法,数据库一多,不同的连接方法就显得杂乱,不整齐,无规矩。
 
 有了 JDBC之后:
 
 总结来说:
- JDBC是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
 - JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
 - JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
 
2.如何使用?
使用JDBC主要从以下入手:
 1、注册驱动
 2、获取连接
 3、创建statement对象
 4、发送SQL语句
 5、结果集解析
 6、关闭资源 【先开后关】
 举例:
 public static void main(String[] args) throws SQLException {
        //1.注册驱动
        /**
         * TODO: 注意
         *   Driver ->5.8及其以上 com.mysql.cj.jdbc.Driver
         * 	 5.8以下 com.mysql.jdbc.Driver
         */
        DriverManager.registerDriver(new Driver());
        //2.获取连接
        /**
         * TODO: 注意
         *   面向接口编程
         *   java.sql 接口 = 实现类
         *   connection 使用java.sql.Connection接口接收
         */
        Connection connection = DriverManager.getConnection("jdbc:mysql://192.168.31.19:3306/atguigu", "root", "root");
        //3.创建小车
        Statement statement = connection.createStatement();
        //4.发送SQL语句
        String sql = "select id,account,password,nickname from t_user ;";
        ResultSet resultSet =  statement.executeQuery(sql);
        //5.结果集解析
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String account = resultSet.getString("account");
            String password = resultSet.getString("password");
            String nickname = resultSet.getString("nickname");
            System.out.println(id+"::"+account+"::"+password+"::"+nickname);
        }
        //6.关闭资源  【先开后关】
        resultSet.close();
        statement.close();
        connection.close();
    }
 
(1)注册驱动
①
/**
*加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传
*递要加载的 JDBC 驱动的类名
*/
Class.forName(“com.mysql.jdbc.Driver”);
 
②
//1.加载配置文件
        InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        
        //2.读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //3.加载驱动
        Class.forName(driverClass);
 
其中,配置文件声明在工程的src目录下:【jdbc.properties】
user=root
password=abc123
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
 
说明:使用配置文件的方式保存配置信息,在代码中加载配置文件
使用配置文件的好处:
①实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码
 ②如果修改了配置信息,省去重新编译的过程。
(2)获取连接
可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
  User,password可以用“属性名=属性值”方式告诉数据库;
  JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的
 驱动程序,从而建立到数据库的连接。
(3)操作数据表
①使用Statement操作数据表
- 通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。
 - Statement 接口中定义了下列方法用于执行 SQL 语句:
 
/**
   * SQL分类:DDL(容器创建、修改、删除) DML(插入、修改、删除) DQL(查询) TPL(事务控制语言)
   * 方式一:
   *  int i = statement.executeUpdate(sql);
   *  参数:sql 非DQL
   *  返回: int
   *      情况1:DML 返回影响行数,例如删除了三条数据 return 3; 插入了两条 return 2
   *      情况2: 非DML return 0;
   * 方式二:
   * ResultSet resultSet = statement.executeQuery(sql);
   * 参数:sql DQL
   * 返回: resultSet 结果封装对象
   *
  */
int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
ResultSet executeQuery(String sql):执行查询操作SELECT
 
-  
但是使用Statement操作数据表存在弊端:
- 问题一:存在拼串操作,繁琐
 - 问题二:存在SQL注入问题
 
 -  
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
 -  
对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。
 
②PreparedStatement
可以通过调用 Connection 对象的 preparedStatement() 方法获取
 PreparedStatement 对象
 PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的
 SQL 语句
 PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调
 用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方
 法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开
 始),第二个是设置的 SQL 语句中的参数的值
 举例:
@Test
 public void test() throws ClassNotFoundException, SQLException {
     Class.forName("com.mysql.cj.jdbc.Driver");
     Connection connection = DriverManager.getConnection(URL, USER, PS);
     String sql = "insert into t_user(account,password,nickname) values (?,?,?);";
     PreparedStatement preparedStatement = connection.prepareStatement(sql);
     preparedStatement.setString(1,"test");
     preparedStatement.setString(2,"1243");
     preparedStatement.setString(3,"user");
     int i = preparedStatement.executeUpdate();
     System.out.println(i);
     preparedStatement.close();
     connection.close();
}
 
3、ResultSet与ResultSetMetaData
(1)ResultSet
-  
查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象
 -  
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现
 -  
ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。
 -  
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。
 -  
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。
- 例如: getInt(1), getString(“name”)
 - 注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。
 
 -  
ResultSet 接口的常用方法:
- boolean next()
 - getString()
 - …

 
 
(2)ResultSetMetaData
-  
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
 -  
ResultSetMetaData meta = rs.getMetaData();
- getColumnName(int column):获取指定列的名称
 - getColumnLabel(int column):获取指定列的别名
 - getColumnCount():返回当前 ResultSet 对象中的列数。
 - getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
 - getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
 - isNullable(int column):指示指定列中的值是否可以为 null。
 - isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。
 
 
关于ResultSetMetaData**
- 如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可
 - 获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法
 - 获取 ResultSet 每一列的列的别名是什么:调用 ResultSetMetaData 的getColumnLabel() 方法

 



















