• JavaWeb开发之JDBC知识总结


    JDBC(Java数据库连接),是一种用于执行SQL语句的Java的API,它由一组Java语言编写的类和接口组成,可以为多种关系型数据库提供统一访问。没有JDBC的时候,如果现在要开发一套系统,使用Java连接MySQL数据库,那么这时候Java程序员需要了解MySQL驱动API,如果使用Java连接Oracle数据库,那么这个时候Java程序员需要了解Oracle数据库驱动API。SUN公司提供一套统一的规范(接口)。然后各个数据库生产商提供这套接口的实现。这套接口规范就是JDBC的规范。

    目录

    1、JDBC入门程序

     2、JDBC的CRUD操作

    3、JDBC之工具类的抽取

    4、JDBC的SQL注入问题及解决

    5、JDBC的CRUD操作之PreparedStatement

    6、JBDC的事务管理

    7、连接池之Druid与C3P0

    8、JDBC之改写工具类

    9、DBUtils的学习之CRUD操作

    10、DBUtils使用之ResultSetHandler实现类


    1、JDBC入门程序

    首先创建数据库和表,并参插入数据,导入连接mysql的jar包,然后编写程序实现:加载驱动,获得连接,执行基本查询操作,释放资源。

    创建数据库和表,插入记录代码如下:

    1. create database if not exists web_test1;
    2. use web_test1;
    3. create table if not exists user(
    4. id int primary key auto_increment,
    5. username varchar(20),
    6. password varchar(20),
    7. nickname varchar(20),
    8. age int
    9. );
    10. insert into user values (null,'aaa','123','小丽',34);
    11. insert into user values (null,'bbb','123','大王',32);
    12. insert into user values (null,'ccc','123','小明',28);
    13. insert into user values (null,'ddd','123','大黄',21);

    jdbc连接数据库,并执行查询语句:
     

    1. import java.sql.*;
    2. public class JDBCDemo01 {
    3. public static void main(String[] args) throws ClassNotFoundException, SQLException {
    4. test() ;
    5. }
    6. private static void test() throws ClassNotFoundException, SQLException {
    7. // 1.加载驱动
    8. Class.forName("com.mysql.jdbc.Driver");
    9. // 2.获得连接
    10. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test1", "root", "123456");
    11. Statement statement = conn.createStatement();
    12. // 3.2编写SQL语句:
    13. String sql = "select * from user";
    14. // 3.3执行SQL:
    15. ResultSet rs = statement.executeQuery(sql);
    16. // 3.4遍历结果集:
    17. while(rs.next()){
    18. System.out.print(rs.getInt("id")+" ");
    19. System.out.print(rs.getString("username")+" ");
    20. System.out.print(rs.getString("password")+" ");
    21. System.out.print(rs.getString("nickname")+" ");
    22. System.out.print(rs.getInt("age"));
    23. System.out.println();
    24. }
    25. // 4.释放资源
    26. rs.close();
    27. statement.close();
    28. conn.close();
    29. }
    30. }

    注意:上述包含了JDBC的几个API

    1)DriverManager:驱动管理类,用于获得连接。

    2)Connection:与数据库连接的对象,用于创建执行SQL语句的对象,主要包括下面三个:

    1. Statement                           :执行SQL
    2. CallableStatement              :执行数据库中存储过程
    3. PreparedStatement            :执行SQL.对SQL进行预处理。解决SQL注入漏洞。

    另外Connection也可以进行事务管理。

     3)Statement对象主要用于执行SQL语句,也可以执行批处理,具体如下:

    1. boolean execute(String sql): 执行查询,修改,添加,删除的SQL语句。
    2. ResultSet executeQuery(String sql):执行查询(执行select语句)。
    3. int executeUpate(String sql):  执行修改,添加,删除的SQL语句。

    4)ResultSet是结果集,一般使用查询语句查到的结果都是一个结果集,对结果集进行遍历使用next()方法。

     2、JDBC的CRUD操作

    使用executeQuery(String sql)方法执行增删改的操作会返回被影响的记录行,使用这个executeUpate(String sql)方法执行查询操作会返回一个ResultSet结果集。最后需要进行资源的释放。

    1. import java.sql.*;
    2. public class JDBCDemo01 {
    3. public static void main(String[] args) {
    4. test() ;
    5. }
    6. private static void test() {
    7. Connection conn = null ;
    8. Statement statement = null ;
    9. ResultSet rs = null ;
    10. try {
    11. // 1.加载驱动
    12. Class.forName("com.mysql.jdbc.Driver");
    13. // 2.获得连接
    14. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test1", "root", "123456");
    15. statement = conn.createStatement();
    16. // 3.2编写SQL语句:
    17. String sql1 = "insert into user values (null,'eee','123','阿黄',21)";
    18. String sql2 = "update user set password='abc',nickname='旺财' where id = 5";
    19. String sql3 = "delete from user where id = 5";
    20. String sql = "select * from user";
    21. // 3.3执行SQL:
    22. int num1 = statement.executeUpdate(sql1);
    23. if (num1 > 0) {
    24. System.out.println("插入成功");
    25. }
    26. int num2 = statement.executeUpdate(sql2);
    27. if (num2 > 0) {
    28. System.out.println("修改成功");
    29. }
    30. int num3 = statement.executeUpdate(sql3);
    31. if (num3 > 0) {
    32. System.out.println("删除成功");
    33. }
    34. rs = statement.executeQuery(sql);
    35. // 3.4遍历结果集:
    36. while (rs.next()) {
    37. System.out.print(rs.getInt("id") + " ");
    38. System.out.print(rs.getString("username") + " ");
    39. System.out.print(rs.getString("password") + " ");
    40. System.out.print(rs.getString("nickname") + " ");
    41. System.out.print(rs.getInt("age"));
    42. System.out.println();
    43. }
    44. }catch (Exception e){
    45. e.printStackTrace();
    46. }finally {
    47. if(rs != null){
    48. try {
    49. rs.close();
    50. } catch (SQLException e) {
    51. e.printStackTrace();
    52. }
    53. rs = null;
    54. }
    55. if(statement != null){
    56. try {
    57. statement.close();
    58. } catch (SQLException e) {
    59. e.printStackTrace();
    60. }
    61. statement = null;
    62. }
    63. if(conn != null){
    64. try {
    65. conn.close();
    66. } catch (SQLException e) {
    67. e.printStackTrace();
    68. }
    69. conn = null;
    70. }
    71. }
    72. }
    73. }

    3、JDBC之工具类的抽取

    因为传统JDBC的开发,注册驱动,获得连接,释放资源这些代码都是重复编写的。所以可以将重复的代码提取到一个类中来完成。

    首先在src目录下创建配置文件db.properties,配置Mysql,后面在工具类中直接加载就可以。

    1. driverClassName=com.mysql.jdbc.Driver
    2. url=jdbc:mysql://localhost:3306/web_test1
    3. username=root
    4. password=123456

    编写工具类:

    1. import java.io.FileInputStream;
    2. import java.io.IOException;
    3. import java.sql.*;
    4. import java.util.Properties;
    5. public class JDBCUtils {
    6. private static String driverClassName;
    7. private static String url;
    8. private static String username;
    9. private static String password;
    10. static{
    11. Properties properties = new Properties() ;
    12. try {
    13. properties.load(new FileInputStream("src/db.properties"));
    14. } catch (IOException e) {
    15. e.printStackTrace();
    16. }
    17. driverClassName=properties.getProperty("driverClassName");
    18. url=properties.getProperty("url");
    19. username=properties.getProperty("username");
    20. password=properties.getProperty("password");
    21. }
    22. /**
    23. * 注册驱动的方法
    24. */
    25. public static void loadDriver(){
    26. try {
    27. Class.forName(driverClassName);
    28. } catch (ClassNotFoundException e) {
    29. e.printStackTrace();
    30. }
    31. }
    32. /**
    33. * 获得连接的方法
    34. */
    35. public static Connection getConnection(){
    36. Connection conn = null;
    37. try{
    38. // 将驱动一并注册:
    39. loadDriver();
    40. // 获得连接
    41. conn = DriverManager.getConnection(url,username, password);
    42. }catch(Exception e){
    43. e.printStackTrace();
    44. }
    45. return conn;
    46. }
    47. /**
    48. * 释放资源的方法
    49. */
    50. public static void release(Statement stmt, Connection conn){
    51. if(stmt != null){
    52. try {
    53. stmt.close();
    54. } catch (SQLException e) {
    55. e.printStackTrace();
    56. }
    57. stmt = null;
    58. }
    59. if(conn != null){
    60. try {
    61. conn.close();
    62. } catch (SQLException e) {
    63. e.printStackTrace();
    64. }
    65. conn = null;
    66. }
    67. }
    68. public static void release(ResultSet rs, Statement stmt, Connection conn){
    69. // 资源释放:
    70. if(rs != null){
    71. try {
    72. rs.close();
    73. } catch (SQLException e) {
    74. e.printStackTrace();
    75. }
    76. rs = null;
    77. }
    78. if(stmt != null){
    79. try {
    80. stmt.close();
    81. } catch (SQLException e) {
    82. e.printStackTrace();
    83. }
    84. stmt = null;
    85. }
    86. if(conn != null){
    87. try {
    88. conn.close();
    89. } catch (SQLException e) {
    90. e.printStackTrace();
    91. }
    92. conn = null;
    93. }
    94. }
    95. }

    调用工具类进行测试:
     

    1. import utils.JDBCUtils;
    2. import java.sql.*;
    3. public class JDBCDemo01 {
    4. public static void main(String[] args) {
    5. test() ;
    6. }
    7. private static void test() {
    8. Connection conn = null ;
    9. Statement statement = null ;
    10. ResultSet rs = null ;
    11. try {
    12. conn = JDBCUtils.getConnection() ;
    13. statement = conn.createStatement();
    14. // 3.2编写SQL语句:
    15. String sql = "select * from user";
    16. // 3.3执行SQL
    17. rs = statement.executeQuery(sql);
    18. // 3.4遍历结果集:
    19. while (rs.next()) {
    20. System.out.print(rs.getInt("id") + " ");
    21. System.out.print(rs.getString("username") + " ");
    22. System.out.print(rs.getString("password") + " ");
    23. System.out.print(rs.getString("nickname") + " ");
    24. System.out.print(rs.getInt("age"));
    25. System.out.println();
    26. }
    27. }catch (Exception e){
    28. e.printStackTrace();
    29. }finally {
    30. JDBCUtils.release(rs,statement,conn);
    31. }
    32. }
    33. }

    4、JDBC的SQL注入问题及解决

    在早期互联网上SQL注入漏洞普遍存在。有一个网站,用户需要进行注册,用户注册以后根据用户名和密码完成登录。假设现在用户名已经被其他人知道了,但是其他人不知道你的密码,也可以登录到网站上进行相应的操作。

    1. 输入用户名
      1. aaa’ or ‘1=1 密码随意
      2. aaa’ --      密码随意

    使用的用户名和密码中带有SQL语句的关键字,使得不需要验证密码即实现登录的功能。

    采用PreparedStatement对象解决SQL注入漏洞。这个对象将SQL预先进行编译,使用?作为占位符。?所代表内容是SQL所固定。再次传入变量(包含SQL的关键字)。这个时候也不会识别这些关键字,就可以避免SQL注入为问题发生。

    5、JDBC的CRUD操作之PreparedStatement

    使用PreparedStatement可以进行预编译SQL,后面不会识别输入的关键子,防止出现SQL注入问题,整个过程如下:首先连接数据库,编写SQL语句,预编译SQL,设置参数,并执行相应的DML操作,最后释放资源。

    1. import utils.JDBCUtils;
    2. import java.sql.*;
    3. public class JDBCDemo01 {
    4. public static void main(String[] args) {
    5. test() ;
    6. }
    7. private static void test() {
    8. Connection conn = null ;
    9. PreparedStatement statement = null ;
    10. ResultSet rs = null ;
    11. try {
    12. conn = JDBCUtils.getConnection() ;
    13. String sql1 = "insert into user values (null,?,?,?,?)";
    14. String sql2 = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";
    15. String sql3 = "delete from user where id = ?";
    16. String sql = "select * from user";
    17. // 插入操作
    18. statement = conn.prepareStatement(sql1);
    19. // 设置参数:
    20. statement.setString(1, "eee");
    21. statement.setString(2, "abc");
    22. statement.setString(3, "旺财");
    23. statement.setInt(4, 32);
    24. // 执行SQL
    25. int num = statement.executeUpdate();
    26. if(num > 0){
    27. System.out.println("插入成功!");
    28. }
    29. // 修改操作
    30. statement = conn.prepareStatement(sql2);
    31. // 设置参数:
    32. statement.setString(1, "abc");
    33. statement.setString(2, "1234");
    34. statement.setString(3, "旺旺");
    35. statement.setInt(4, 23);
    36. statement.setInt(5, 6);
    37. // 执行SQL:
    38. num = statement.executeUpdate();
    39. if(num > 0){
    40. System.out.println("修改成功!");
    41. }
    42. //删除操作
    43. statement = conn.prepareStatement(sql3);
    44. statement.setInt(1,4);
    45. num = statement.executeUpdate();
    46. if(num > 0){
    47. System.out.println("删除成功!");
    48. }
    49. //查询操作
    50. statement = conn.prepareStatement(sql);
    51. rs = statement.executeQuery(sql);
    52. // 3.4遍历结果集:
    53. while (rs.next()) {
    54. System.out.print(rs.getInt("id") + " ");
    55. System.out.print(rs.getString("username") + " ");
    56. System.out.print(rs.getString("password") + " ");
    57. System.out.print(rs.getString("nickname") + " ");
    58. System.out.print(rs.getInt("age"));
    59. System.out.println();
    60. }
    61. }catch (Exception e){
    62. e.printStackTrace();
    63. }finally {
    64. JDBCUtils.release(rs,statement,conn);
    65. }
    66. }
    67. }

    6、JBDC的事务管理

    事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全都成功,要么全都失败。进行事务管理之前,我们先进行数据准备,创建一个数据库和表,并插入一些数据,具体如下:

    1. create database if not exists web_test1;
    2. use web_test1;
    3. create table account(
    4. id int primary key auto_increment,
    5. name varchar(20),
    6. money double
    7. );
    8. insert into account values (null,'aaa',10000);
    9. insert into account values (null,'bbb',10000);
    10. insert into account values (null,'ccc',10000);

    事务管理常用的API包括开启事务,提交事务,事务回滚,具体如下:

    通过下面的的转账案例学习JDBC的事务管理,首先开启事务,在整个事务执行过程中没有发生异常则提交事务,否则回滚事务到最初的状态。

    1. import utils.JDBCUtils;
    2. import java.sql.Connection;
    3. import java.sql.PreparedStatement;
    4. import java.sql.SQLException;
    5. public class JDBCDemo02 {
    6. public static void main(String[] args) {
    7. demo1() ;
    8. }
    9. public static void demo1() {
    10. Connection conn = null;
    11. PreparedStatement pstmt = null;
    12. try {
    13. /**
    14. * 完成转账代码:
    15. * * 扣除某个账号的钱
    16. * * 给另外一个账号加钱
    17. */
    18. // 获得连接:
    19. conn = JDBCUtils.getConnection();
    20. // 开启事务
    21. conn.setAutoCommit(false);
    22. // 编写SQL语句:
    23. String sql = "update account set money = money + ? where name = ?";
    24. // 预编译SQL:
    25. pstmt = conn.prepareStatement(sql);
    26. // 设置参数:
    27. // 用aaa账号给bbb账号转1000元
    28. pstmt.setDouble(1, -1000);
    29. pstmt.setString(2, "aaa");
    30. // 执行SQL:扣除aaa账号1000元
    31. pstmt.executeUpdate();
    32. //int i = 1 / 0;
    33. // 给bbb账号加1000
    34. pstmt.setDouble(1, 1000);
    35. pstmt.setString(2, "bbb");
    36. pstmt.executeUpdate();
    37. // 提交事务:
    38. conn.commit();
    39. } catch (Exception e) {
    40. // 回滚事务:
    41. try {
    42. conn.rollback();
    43. } catch (SQLException e1) {
    44. e1.printStackTrace();
    45. }
    46. e.printStackTrace();
    47. } finally {
    48. JDBCUtils.release(pstmt, conn);
    49. }
    50. }
    51. }

    7、连接池之Druid与C3P0

    连接池是装有连接的容器,使用连接的话,可以从连接池中进行获取,使用完成之后将连接归还给连接池。连接对象创建和销毁是需要耗费时间的,在服务器初始化的时候就初始化一些连接。把这些连接放入到内存中,使用的时候可以从内存中获取,使用完成之后将连接放入连接池中。从内存中获取和归还的效率要远远高于创建和销毁的效率。(提升性能)。

    我们先来看第一个连接池,Druid阿里旗下开源连接池产品,使用非常简单,可以与Spring框架进行快速整合。

    首先需要引入连接数据库的jar包和连接池的jar包,具体如下:

    下面从连接池中直接获得连接,编写SQL语句,预编译,然后进行查询操作,最后释放资源。

    1. import com.alibaba.druid.pool.DruidDataSource;
    2. import utils.JDBCUtils;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. public class JDBCDemo02 {
    7. public static void main(String[] args) {
    8. demo1() ;
    9. }
    10. public static void demo1(){
    11. Connection conn = null;
    12. PreparedStatement pstmt = null;
    13. ResultSet rs = null;
    14. try{
    15. // 使用连接池:
    16. DruidDataSource dataSource = new DruidDataSource();
    17. // 手动设置数据库连接的参数:
    18. dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    19. dataSource.setUrl("jdbc:mysql:///web_test1");
    20. dataSource.setUsername("root");
    21. dataSource.setPassword("123456");
    22. // 获得连接:
    23. // conn = JDBCUtils.getConnection();
    24. conn = dataSource.getConnection();
    25. // 编写SQL:
    26. String sql = "select * from account";
    27. // 预编译SQL:
    28. pstmt = conn.prepareStatement(sql);
    29. // 设置参数:
    30. // 执行SQL:
    31. rs = pstmt.executeQuery();
    32. while(rs.next()){
    33. System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "+rs.getDouble("money"));
    34. }
    35. }catch(Exception e){
    36. e.printStackTrace();
    37. }finally{
    38. JDBCUtils.release(rs, pstmt, conn);
    39. }
    40. }
    41. }

     上面的连接池案例是使用手动配置MySQL参数的方法,我们将配置参数卸载.properties文件中,通过加载配置文件的方式获取配置参数,具体如下:

    1. import com.alibaba.druid.pool.DruidDataSourceFactory;
    2. import utils.JDBCUtils;
    3. import javax.sql.DataSource;
    4. import java.io.FileInputStream;
    5. import java.sql.Connection;
    6. import java.sql.PreparedStatement;
    7. import java.sql.ResultSet;
    8. import java.util.Properties;
    9. public class JDBCDemo02 {
    10. public static void main(String[] args) {
    11. demo1() ;
    12. }
    13. public static void demo1(){
    14. Connection conn = null;
    15. PreparedStatement pstmt = null;
    16. ResultSet rs = null;
    17. try{
    18. // 配置文件的方式获取配置参数
    19. Properties properties = new Properties();
    20. properties.load(new FileInputStream("src/db.properties"));
    21. DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    22. // 获得连接:
    23. conn = dataSource.getConnection();
    24. // 编写SQL:
    25. String sql = "select * from account";
    26. // 预编译SQL:
    27. pstmt = conn.prepareStatement(sql);
    28. // 设置参数:
    29. // 执行SQL:
    30. rs = pstmt.executeQuery();
    31. while(rs.next()){
    32. System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "+rs.getDouble("money"));
    33. }
    34. }catch(Exception e){
    35. e.printStackTrace();
    36. }finally{
    37. JDBCUtils.release(rs, pstmt, conn);
    38. }
    39. }
    40. }

    我们下面学习另外一个开源的连接池C3P0,首先我们需要导入相关jar包,具体如下:

     首先我们使用手动设置MySQL参数的方式使用C3P0连接池,首先创建连接,设置参数,然后从连接池获得连接,后面就可以写SQL语句,预编译并执行查询操作了,具体如下:

    1. import com.mchange.v2.c3p0.ComboPooledDataSource;
    2. import utils.JDBCUtils;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. public class JDBCDemo02 {
    7. public static void main(String[] args) {
    8. demo1() ;
    9. }
    10. public static void demo1(){
    11. Connection conn = null;
    12. PreparedStatement pstmt = null;
    13. ResultSet rs = null;
    14. try{
    15. // 创建连接池:
    16. ComboPooledDataSource dataSource = new ComboPooledDataSource();
    17. // 设置连接参数:
    18. dataSource.setDriverClass("com.mysql.jdbc.Driver");
    19. dataSource.setJdbcUrl("jdbc:mysql:///web_test1");
    20. dataSource.setUser("root");
    21. dataSource.setPassword("123456");
    22. // 从连接池中获得连接:
    23. conn = dataSource.getConnection();
    24. // 编写SQL:
    25. String sql = "select * from account";
    26. // 预编译SQL:
    27. pstmt = conn.prepareStatement(sql);
    28. // 执行SQL:
    29. rs = pstmt.executeQuery();
    30. while(rs.next()){
    31. System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "+rs.getDouble("money"));
    32. }
    33. }catch(Exception e){
    34. e.printStackTrace();
    35. }finally{
    36. JDBCUtils.release(rs, pstmt, conn);
    37. }
    38. }
    39. }

    下面将数据库的参数配置在c3p0-config.xml文件中,这样会自动加载配置,不粗要在程序中设置数据库的配置信息,具体如下,包含两种配置,一种是默认配置,另外一种是带名称参数的配置。

    1. "1.0" encoding="UTF-8"?>
    2. <c3p0-config>
    3. <default-config>
    4. <property name="jdbcUrl">jdbc:mysql://localhost:3306/web_test1?useUnicode=true&characterEncoding=utf-8property>
    5. <property name="driverClass">com.mysql.jdbc.Driverproperty>
    6. <property name="user">rootproperty>
    7. <property name="password">123456property>
    8. <property name="acquireIncrement">3property>
    9. <property name="initialPoolSize">10property>
    10. <property name="minPoolSize">2property>
    11. <property name="maxPoolSize">10property>
    12. default-config>
    13. <named-config name="otherConfig">
    14. <property name="jdbcUrl">jdbc:mysql://localhost:3306/web_test1?useUnicode=true&characterEncoding=utf-8property>
    15. <property name="driverClass">com.mysql.jdbc.Driverproperty>
    16. <property name="user">rootproperty>
    17. <property name="password">123456property>
    18. <property name="acquireIncrement">3property>
    19. <property name="initialPoolSize">10property>
    20. <property name="minPoolSize">2property>
    21. <property name="maxPoolSize">10property>
    22. named-config>
    23. c3p0-config>

    加载配置文件并从连接池获得连接,然后编写SQL语句,预编译并执行查询操作的代码如下:

    1. import com.mchange.v2.c3p0.ComboPooledDataSource;
    2. import utils.JDBCUtils;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. public class JDBCDemo02 {
    7. public static void main(String[] args) {
    8. demo1() ;
    9. }
    10. public static void demo1(){
    11. Connection conn = null;
    12. PreparedStatement pstmt = null;
    13. ResultSet rs = null;
    14. try{
    15. // 创建连接池:
    16. ComboPooledDataSource dataSource = new ComboPooledDataSource();
    17. // 从连接池中获得连接:
    18. conn = dataSource.getConnection();
    19. // 编写SQL:
    20. String sql = "select * from account";
    21. // 预编译SQL:
    22. pstmt = conn.prepareStatement(sql);
    23. // 执行SQL:
    24. rs = pstmt.executeQuery();
    25. while(rs.next()){
    26. System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "+rs.getDouble("money"));
    27. }
    28. }catch(Exception e){
    29. e.printStackTrace();
    30. }finally{
    31. JDBCUtils.release(rs, pstmt, conn);
    32. }
    33. }
    34. }

    8、JDBC之改写工具类

    之前的工具类是使用传统的方式获得连接,现在直接在工具类中创建连接,每次直接使用即可,不用重复创建,具体如下:

    1. import com.mchange.v2.c3p0.ComboPooledDataSource;
    2. import javax.sql.DataSource;
    3. import java.sql.*;
    4. public class JDBCUtils02 {
    5. private static final ComboPooledDataSource datasource = new ComboPooledDataSource() ;
    6. public static DataSource getDataSource(){
    7. return datasource ;
    8. }
    9. public static Connection getConnection(){
    10. Connection conn = null;
    11. try{
    12. conn = datasource.getConnection() ;
    13. }catch(Exception e){
    14. e.printStackTrace();
    15. }
    16. return conn;
    17. }
    18. public static void release(Statement stmt, Connection conn){
    19. if(stmt != null){
    20. try {
    21. stmt.close();
    22. } catch (SQLException e) {
    23. e.printStackTrace();
    24. }
    25. stmt = null;
    26. }
    27. if(conn != null){
    28. try {
    29. conn.close();
    30. } catch (SQLException e) {
    31. e.printStackTrace();
    32. }
    33. conn = null;
    34. }
    35. }
    36. public static void release(ResultSet rs, Statement stmt, Connection conn){
    37. // 资源释放:
    38. if(rs != null){
    39. try {
    40. rs.close();
    41. } catch (SQLException e) {
    42. e.printStackTrace();
    43. }
    44. rs = null;
    45. }
    46. if(stmt != null){
    47. try {
    48. stmt.close();
    49. } catch (SQLException e) {
    50. e.printStackTrace();
    51. }
    52. stmt = null;
    53. }
    54. if(conn != null){
    55. try {
    56. conn.close();
    57. } catch (SQLException e) {
    58. e.printStackTrace();
    59. }
    60. conn = null;
    61. }
    62. }
    63. }

    9、DBUtils的学习之CRUD操作

    DBUtils是Apache提供的一个对JDBC进行简单封装的工具类,可以简化JDBC应用的开发。JDBC手写比较麻烦,而且有非常多的代码是类似的。比如获得连接,预编译SQL,释放资源等..那么可以将这些代码抽取出来放到工具类中。将类似的代码进行抽取。大大简化JDBC的编程。

    它的核心运行类对象是QueryRunner对象,该对象有一些常用的API

     通过QueryRunner核心运行类是西安CRUD操作,不需要预编译之类的,当然这个也需要导入相关jar包,代码具体如下:

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.ResultSetHandler;
    3. import java.sql.ResultSet;
    4. import java.sql.SQLException;
    5. import java.util.ArrayList;
    6. import java.util.List;
    7. public class DBUtils {
    8. public static void main(String[] args) throws SQLException {
    9. test() ;
    10. }
    11. private static void test() throws SQLException {
    12. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource());
    13. //添加操作
    14. queryRunner.update("insert into account values (null,?,?)", "ddd",10000);
    15. //修改操作
    16. queryRunner.update("update account set name=?,money=? where id =?", "eee",20000,4);
    17. //删除操作
    18. queryRunner.update("delete from account where id = ?", 3);
    19. //查询一条记录的操作
    20. Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler() {
    21. @Override
    22. public Account handle(ResultSet resultSet) throws SQLException {
    23. Account account = new Account() ;
    24. while(resultSet.next()){
    25. account.setId(resultSet.getInt("id"));
    26. account.setName(resultSet.getString("name"));
    27. account.setMoney(resultSet.getDouble("money"));
    28. }
    29. return account ;
    30. }
    31. }, 1) ;
    32. System.out.println(account);
    33. //查询多条语句
    34. List list = queryRunner.query("select * from account", new ResultSetHandler>() {
    35. @Override
    36. public List handle(ResultSet resultSet) throws SQLException {
    37. List list = new ArrayList<>();
    38. while(resultSet.next()){
    39. Account account = new Account() ;
    40. account.setId(resultSet.getInt("id"));
    41. account.setName(resultSet.getString("name"));
    42. account.setMoney(resultSet.getDouble("money"));
    43. list.add(account) ;
    44. }
    45. return list ;
    46. }
    47. }) ;
    48. for(Account account1 : list){
    49. System.out.println(account1);
    50. }
    51. }
    52. }

    10、DBUtils使用之ResultSetHandler实现类

    1)ArrayHandler和ArrayListHandler

    一条记录封装到一个数组当中。这个数组应该是Object[]

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.ArrayHandler;
    3. import java.sql.SQLException;
    4. import java.util.Arrays;
    5. public class DBUtils02 {
    6. public static void main(String[] args) throws SQLException {
    7. test() ;
    8. }
    9. private static void test() throws SQLException {
    10. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    11. Object [] objects = queryRunner.query("select * from account where id = ?",new ArrayHandler(),1) ;
    12. System.out.println(Arrays.toString(objects));
    13. }
    14. }

    将多条记录封装到一个装有Object[]的List集合中。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.ArrayListHandler;
    3. import java.sql.SQLException;
    4. import java.util.Arrays;
    5. import java.util.List;
    6. public class DBUtils02 {
    7. public static void main(String[] args) throws SQLException {
    8. test() ;
    9. }
    10. private static void test() throws SQLException {
    11. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    12. List list = queryRunner.query("select * from account ",new ArrayListHandler()) ;
    13. for(Object [] objects : list) {
    14. System.out.println(Arrays.toString(objects));
    15. }
    16. }
    17. }

    2)BeanHandlerBeanListHandler

    将一条记录封装到一个JavaBean中。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.BeanHandler;
    3. import java.sql.SQLException;
    4. public class DBUtils02 {
    5. public static void main(String[] args) throws SQLException {
    6. test() ;
    7. }
    8. private static void test() throws SQLException {
    9. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    10. Account account = queryRunner.query("select * from account where id = ?",new BeanHandler(Account.class),1) ;
    11. System.out.println(account);
    12. }
    13. }

    将多条记录封装到一个装有JavaBean的List集合中。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.BeanListHandler;
    3. import java.sql.SQLException;
    4. import java.util.List;
    5. public class DBUtils02 {
    6. public static void main(String[] args) throws SQLException {
    7. test() ;
    8. }
    9. private static void test() throws SQLException {
    10. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    11. List account = queryRunner.query("select * from account",new BeanListHandler(Account.class)) ;
    12. for(Account account1 : account){
    13. System.out.println(account1);
    14. }
    15. }
    16. }

    3)MapHandler和MapListHandler

    将一条记录封装到一个Map集合中,Map的key是列名,Map的value就是表中列的记录值。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.MapHandler;
    3. import java.sql.SQLException;
    4. import java.util.Map;
    5. public class DBUtils02 {
    6. public static void main(String[] args) throws SQLException {
    7. test() ;
    8. }
    9. private static void test() throws SQLException {
    10. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    11. Map map = queryRunner.query("select * from account where id = ?",new MapHandler(),1) ;
    12. System.out.println(map);
    13. }
    14. }

    将多条记录封装到一个装有Map的List集合中。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.MapListHandler;
    3. import java.sql.SQLException;
    4. import java.util.List;
    5. import java.util.Map;
    6. public class DBUtils02 {
    7. public static void main(String[] args) throws SQLException {
    8. test() ;
    9. }
    10. private static void test() throws SQLException {
    11. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    12. List> list = queryRunner.query("select * from account",new MapListHandler()) ;
    13. for(Map map : list){
    14. System.out.println(map);
    15. }
    16. }
    17. }

    4)ColumnListHandler、ScalarHandler

    将数据中的某列封装到List集合中。

    1. import org.apache.commons.dbutils.QueryRunner;
    2. import org.apache.commons.dbutils.handlers.ColumnListHandler;
    3. import java.sql.SQLException;
    4. import java.util.List;
    5. public class DBUtils02 {
    6. public static void main(String[] args) throws SQLException {
    7. test() ;
    8. }
    9. private static void test() throws SQLException {
    10. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
    11. List list = queryRunner.query("select * from account",new ColumnListHandler("name")) ;
    12. for(Object object : list){
    13. System.out.println(object);
    14. }
    15. }
    16. }
    17. 将单个值封装。

      1. import org.apache.commons.dbutils.QueryRunner;
      2. import org.apache.commons.dbutils.handlers.ScalarHandler;
      3. import java.sql.SQLException;
      4. public class DBUtils02 {
      5. public static void main(String[] args) throws SQLException {
      6. test() ;
      7. }
      8. private static void test() throws SQLException {
      9. QueryRunner queryRunner = new QueryRunner(JDBCUtils02.getDataSource()) ;
      10. Object object = queryRunner.query("select count(*) from account",new ScalarHandler()) ;
      11. System.out.println(object);
      12. }
      13. }
    18. 相关阅读:
      工业物联网—故障诊断的理论基础
      关于跨域访问
      异常exception和错误error即推荐用法@sneakythrow
      Anaconda创建新环境以及应用到Pycharm项目中
      C++ 类和对象(一)
      docker dify平台接入xinference模型时输入ip总提示拒绝访问
      脉宽调制(PWM)开关驱动
      Java面试题之迭代器Iterator是什么?
      分享几个.NET开源的AI和LLM相关项目框架
      7.自定义凸多边形
    19. 原文地址:https://blog.csdn.net/nuist_NJUPT/article/details/126400998