1 準(zhǔn)備
專注于為中小企業(yè)提供做網(wǎng)站、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)梁山免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了數(shù)千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
2: 兩個(gè)問題
業(yè)務(wù)背景:系統(tǒng)中所有實(shí)體對象都涉及到基本的CRUD操作。所有實(shí)體的CUD操作代碼基本相同,僅僅是發(fā)送給數(shù)據(jù)庫的sql語句不同而已,因此可以把CUD操作的所有相同代碼抽取到工具類的一個(gè)update方法中,并定義參數(shù)接收變化的sql語句。
實(shí)體的R操作,除sql語句不同之外,根據(jù)操作的實(shí)體不同,對ResultSet的映射也各不相同,因此可定義一個(gè)query方法,除以參數(shù)形式接收變化的sql語句外,可以使用策略模式由query方法的調(diào)用者決定如何把ResultSet中的數(shù)據(jù)映射到實(shí)體對象中。
3: JDBC 封裝 update query方法
public class JdbcNewUtils { private JdbcNewUtils() {} /** * 這里可以使用properties進(jìn)行替換 */ 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 返回影響數(shù)目 * @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; } /** * 查詢結(jié)果封裝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; } /** * 關(guān)閉所有打開的資源 */ 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(); } } } /** * 關(guān)閉所有打開的資源 */ 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
每次查詢根據(jù)查詢的參數(shù)不同, 返回的ResultSet 也不同, 這個(gè)規(guī)則我們需要單獨(dú)編寫規(guī)則解析器, 這里用到了策略設(shè)計(jì)模式,
將ResultSetHandler 定義解決問題的接口, handle為那些需要實(shí)現(xiàn)的具體解決的辦法
public interface ResultSetHandler { Object handle(ResultSet resultSet); }
下面我實(shí)現(xiàn)了Beanhandler 和 BeanListHandler 分別是 單個(gè)的Bean 和一個(gè)列表的Bean
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; } }
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
5 測試
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"; ArrayListlist = (ArrayList ) JdbcNewUtils.query(sql2, new Object[] {}, new BeanListHandler(Student.class)); System.out.println(list); } }
6: 總結(jié)
Update系列操作:
對于CUD操作,SQL只有站位符號的多少發(fā)生了改變,對于傳遞參數(shù)才是我們需要關(guān)注的地方,但是JDBC提供了一系列傳遞參數(shù)解析的辦法,通過set系列函數(shù),將參數(shù)值傳遞進(jìn)行,所以我們只需要封裝一個(gè)通用的update即可
Query系列操作
對R操作,就復(fù)雜得多,SQL語句的不同,返回的ResultSet也不同,可以單個(gè)Bean 或者一個(gè)List,一個(gè)Map等,可以看出來,實(shí)際上很多框架提供的也就是這些方法的封裝
對了 真正應(yīng)用上 我們的DAO 一邊是 下面的寫法
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)); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。