写在后面
在浏览本文之前,你或者应该先理解:
- JDBC的实现步骤(注册驱动、建设连贯、发送SQL、处理结果集)
- 数据库连接池的应用(本文应用
c3p0
连接池)
DbUtils是Apache的一个对于数据库操作的封装类,本文重写了DbUtils的query与update办法,而代码着重于封装的实现原理,对于很多异样等都未做具体的解决。
实现步骤
- 首先,通过
c3p0
连接池建设数据库连贯,并获取连贯对象。
- 导入
c3p0-0.9.2-pre1.jar
- 创立
c3p0.properties
或c3p0-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&useSSL=false&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; } }
- 数据库增删查改的类
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]); } } }
- 创立对立的解决
ResultSet
后果集的接口类MyResultSetHandler
/** * @Auther dbc * @Date 2020/9/11 17:04 */public interface MyResultSetHandler<T> { T handle(ResultSet resultSet) throws SQLException; }
- 实现上一步的接口
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; } }
- 对于后果集为多个,须要用List来接管,同样用一个接口来继承
MyResultSetHandler
并实现即可,本文就不再做演示。 - 减少测试类Account,数据库也该当存在此表即一些测试数据。次要有以下字段:
private int id; private String name; private Double money;//留神:mysql中定义decimal字段,应由BigDecimal来接管
- 测试
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); }