写在后面

在浏览本文之前,你或者应该先理解:

  • JDBC的实现步骤(注册驱动、建设连贯、发送SQL、处理结果集)
  • 数据库连接池的应用(本文应用c3p0连接池)

DbUtils是Apache的一个对于数据库操作的封装类,本文重写了DbUtils的query与update办法,而代码着重于封装的实现原理,对于很多异样等都未做具体的解决。

实现步骤

  1. 首先,通过c3p0连接池建设数据库连贯,并获取连贯对象。
  • 导入c3p0-0.9.2-pre1.jar
  • 创立c3p0.propertiesc3p0-config.xml文件,上面是.xml文件次要内容:
<?xml version="1.0" encoding="UTF-8"?>  <c3p0-config>   <!-- 默认配置,当应用ComboPooledDataSource无参结构器时,应用的就是这个配置 -->   <default-config>   <!-- 根本配置 -->   <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/share?serverTimezone=Asia/Shanghai&amp;useSSL=false&amp;characterEncoding=utf8</property>   <property name="driverClass">com.mysql.cj.jdbc.Driver</property>   <property name="user">root</property>   <property name="password">123456</property>   <!-- 每次增量,当须要创立Connection对象时,一次创立几个 -->   <property name="acquireIncrement">3</property>   <!-- 当创立池对象后,池中应该有几个Connection对象 -->   <property name="initialPoolSize">10</property>   <!-- 池中起码Connection个数,如果少于这个值,就会创立Connection -->   <property name="minPoolSize">2</property>   <!-- 池中最大连贯个数 -->   <property name="maxPoolSize">15</property>   </default-config></c3p0-config> 
  • 创立数据库连接池,获取连贯对象的包装类JdbcUtil
public class JdbcUtil {      private static ComboPooledDataSource dataSource = new ComboPooledDataSource();     public static Connection getConnection(){          Connection conn = null;   try {              conn = dataSource.getConnection();   } catch (SQLException e) {              e.printStackTrace();   }          return conn;   }        public static DataSource getDataSource(){          return dataSource;   }  }
  1. 数据库增删查改的类MyRunner
public class MyRunner {      private DataSource dataSource;     public MyRunner(DataSource dataSource){          this.dataSource = dataSource;   }        public <T> T query(String sql, MyResultSetHandler<T> handler, Object... params){          T result = null;   try {              Connection conn = dataSource.getConnection();   PreparedStatement pstmt = conn.prepareStatement(sql);   generateParams(pstmt, params); // 给pstmt赋值   result = handler.handle(pstmt.executeQuery());   } catch (SQLException e) {              e.printStackTrace();   }          return result;   }        /**   * 数据操作 包含增、删、改   * @param sql sql语句   * @param params 参数列表   */   public void update(String sql, Object... params){          try {              Connection conn = dataSource.getConnection();   PreparedStatement pstmt = conn.prepareStatement(sql);   generateParams(pstmt, params); // 给pstmt赋值   pstmt.executeUpdate();   } catch (SQLException e) {              e.printStackTrace();   }      }        /**   * 给指定的pstmt 预处理的? 赋值   * @param pstmt PreparedStatement   * @param params 参数列表   * @throws SQLException   */ private static void generateParams(PreparedStatement pstmt, Object[] params) throws SQLException {          for(int i = 1; i <= params.length; i++){              pstmt.setObject(i, params[i-1]);   }      }  }
  1. 创立对立的解决ResultSet后果集的接口类MyResultSetHandler
/**   * @Auther dbc   * @Date 2020/9/11 17:04   */public interface MyResultSetHandler<T> {      T handle(ResultSet resultSet) throws SQLException;  }
  1. 实现上一步的接口MyBeanHandler
public class MyBeanHandler<T> implements MyResultSetHandler<T> {        private Class<T> clazz;     public MyBeanHandler(Class<T> T){          this.clazz = T;   }          @Override   public T handle(ResultSet resultSet) throws SQLException {          T t = null;   if(resultSet.next()){              try {                  t = clazz.newInstance();   ResultSetMetaData metaData = resultSet.getMetaData();   int columnCount = metaData.getColumnCount();   for(int i = 1; i <= columnCount; i++){                      String columnName = metaData.getColumnName(i);   Object columnValue = resultSet.getObject(columnName);   try {                          Field field = clazz.getDeclaredField(columnName);   field.setAccessible(true); // 获取拜访操作权限   field.set(t, columnValue);   }catch (NoSuchFieldException e){                          e.printStackTrace();   }                  }              } catch (InstantiationException | IllegalAccessException e) {                  e.printStackTrace();   }          }          return t;   }    }
  1. 对于后果集为多个,须要用List来接管,同样用一个接口来继承MyResultSetHandler并实现即可,本文就不再做演示。
  2. 减少测试类Account,数据库也该当存在此表即一些测试数据。次要有以下字段:
private int id;  private String name;  private Double money;//留神:mysql中定义decimal字段,应由BigDecimal来接管
  1. 测试
public static void main(String[] args)  {      MyRunner myRunner= new MyRunner(JdbcUtil.getDataSource());   Account account = myRunner.query("SELECT * FROM account WHERE id =?;",new MyBeanHandler<Account>(Account.class),1);   System.out.println(account);   List<Account> accounts = myRunner.query("SELECT * FROM account",new MyBeanListHandler<>(Account.class));   System.out.println(accounts);  }