1 准备
- JDBC 基本知识
- JDBC元数据知识
- 反射基本知识
2: 两个问题
业务背景:系统中所有实体对象都涉及到基本的CRUD操作。所有实体的CUD操作代码基本相同,仅仅是发送给数据库的sql语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的sql语句。
实体的R操作,除sql语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可定义一个query方法,除以参数形式接收变化的sql语句外,可以使用策略模式由query方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
3: JDBC 封装 update query方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | public class JdbcNewUtils { private JdbcNewUtils() {} /** * 这里可以使用properties进行替换 */ private static final String USER = "root" ; private static final String PWD = "root" ; private static final String URL = "jdbc:mysql://127.0.0.1:3306/day?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&generateSimpleParameterMetadata=true" ; private static final String DRIVER= "com.mysql.jdbc.Driver" ; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { Connection connection = DriverManager.getConnection(URL, USER, PWD); return connection; } /** * CUD 返回影响数目 * @param sql * @param args * @return int */ public static int update(String sql,Object [] args) { PreparedStatement ps = null ; Connection conn = null ; try { conn=getConnection(); ps = conn.prepareStatement(sql); for ( int i = 1 ; i <= args.length; i++) { ps.setObject(i, args[i- 1 ]); } return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { close(conn, ps); } return 0 ; } /** * 查询结果封装Bean * @param sql * @param args * @param rsh * @return Object */ public static Object query(String sql,Object [] args,ResultSetHandler rsh) { PreparedStatement ps = null ; Connection conn = null ; try { conn=getConnection(); ps = conn.prepareStatement(sql); for ( int i = 0 ; i < args.length; i++) { ps.setObject(i+ 1 , args[i]); } return rsh.handle(ps.executeQuery()); } catch (SQLException e) { e.printStackTrace(); } finally { close(conn, ps); } return null ; } /** * 关闭所有打开的资源 */ public static void close(Connection conn, Statement stmt) { if (stmt!= null ) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn!= null ) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 关闭所有打开的资源 */ public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs!= null ) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } close(conn, stmt); } } |
4: query
每次查询根据查询的参数不同, 返回的ResultSet 也不同, 这个规则我们需要单独编写规则解析器, 这里用到了策略设计模式,
将ResultSetHandler 定义解决问题的接口, handle为那些需要实现的具体解决的办法
1 2 3 | public interface ResultSetHandler { Object handle(ResultSet resultSet); } |
下面我实现了Beanhandler 和 BeanListHandler 分别是 单个的Bean 和一个列表的Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package jdbc.simpleframwork; import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; public class BeanHandler implements ResultSetHandler { private Class<?> obj; public BeanHandler(Class<?> obj) { this .obj = obj; } @Override public Object handle(ResultSet resultSet){ try { if (!resultSet.next()) { return null ; } Object instance = obj.newInstance(); ResultSetMetaData metaData = resultSet.getMetaData(); int count = metaData.getColumnCount(); for ( int i= 1 ;i<=count;i++) { Field f = obj.getDeclaredField(metaData.getColumnName(i)); f.setAccessible( true ); f.set(instance, resultSet.getObject(i)); } return instance; } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } return null ; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package jdbc.simpleframwork; import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; public class BeanListHandler implements ResultSetHandler { private Class<?> clazz; public BeanListHandler(Class<?> clazz) { super (); this .clazz = clazz; } @Override public Object handle(ResultSet resultSet) { try { ArrayList<Object> objlist = new ArrayList<>(); ResultSetMetaData metaData = resultSet.getMetaData(); int count = metaData.getColumnCount(); while (resultSet.next()) { Object instace = clazz.newInstance(); for ( int i = 0 ; i < count; i++) { Field f = clazz.getDeclaredField(metaData.getColumnName(i + 1 )); f.setAccessible( true ); f.set(instace, resultSet.getObject(i + 1 )); f.setAccessible( false ); } objlist.add(instace); } return objlist; } catch (Exception e) { e.printStackTrace(); } return null ; } } |
5 测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class TestFramwork { public static void main(String[] args) throws SQLException { Connection conn = JdbcNewUtils.getConnection(); String sql = "select * from student where id=?" ; PreparedStatement ps = conn.prepareStatement(sql); Student stu = (Student) JdbcNewUtils.query(sql, new Object[] { 1 }, new BeanHandler(Student. class )); System.out.println(stu); String sql2 = "select * from student" ; ArrayList<Student> list = (ArrayList<Student>) JdbcNewUtils.query(sql2, new Object[] {}, new BeanListHandler(Student. class )); System.out.println(list); } } |
6: 总结
Update系列操作:
对于CUD操作,SQL只有站位符号的多少发生了改变,对于传递参数才是我们需要关注的地方,但是JDBC提供了一系列传递参数解析的办法,通过set系列函数,将参数值传递进行,所以我们只需要封装一个通用的update即可
Query系列操作
对R操作,就复杂得多,SQL语句的不同,返回的ResultSet也不同,可以单个Bean 或者一个List,一个Map等,可以看出来,实际上很多框架提供的也就是这些方法的封装
对了 真正应用上 我们的DAO 一边是 下面的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class AccountDao { public void add(Account account) throws SQLException{ String sql = "insert into account(name , money) values(?, ?)" ; Object[] params = {account.getName(), account.getMoney()}; JdbcUtils.update(sql, params); } public void delete( int id ) throws SQLException{ String sql = "delete from account where id = ?" ; Object[] params = {id}; JdbcUtils.update(sql, params); } public void update(Account account) throws SQLException{ String sql = "update account set name = ?, money = ? where id = ?" ; Object params[] = {account.getName(), account.getMoney(), account.getId()}; JdbcUtils.update(sql, params); } public Account find( int id ) throws SQLException{ String sql = "select * from account where id = ?" ; Object params[] = {id}; return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account. class )); } public List getAll() throws SQLException{ String sql = "select * from account" ; Object params[] = {}; return (List)JdbcUtils.query(sql, params, new BeanListHandler(Account. class )); } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/181271/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)