抽取JDBCTemplate
抽取JDBCTemplate
為了解決DAO實現類中程式碼的重複問題,另外使得程式碼更通用,所以抽取一個公共的模板,使其更具有通用性。
DAO實現類的程式碼
public class StudentDAOImpl implements IStudentDAO { public void save(Student stu) { String sql = "INSERT INTO s_student(name,age) VALUES(?,?)"; Connection conn = null; PreparedStatement ps = null; try { //載入註冊驅動,獲取連線物件 conn = JdbcUtil.getConn(); ps = conn.prepareStatement(sql); ps.setString(1, stu.getName()); ps.setInt(2, stu.getAge()); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 JdbcUtil.close(conn, ps, null); } } public void delete(Long id) { String sql = "DELETE FROM s_student WHERE id = ?"; Connection conn = null; PreparedStatement ps = null; try { //載入註冊驅動 //獲取連線物件 conn = JdbcUtil.getConn(); //獲取語句物件 ps = conn.prepareStatement(sql); ps.setLong(1, id); //執行sql語句 ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 JdbcUtil.close(conn, ps, null); } } public void update(Student newStu) { String sql = "UPDATE s_student SET name = ?,age = ? WHERE id = ?;"; Connection conn = null; PreparedStatement ps = null; try { //載入註冊驅動 //獲取連線物件 conn = JdbcUtil.getConn(); //獲取語句物件 ps = conn.prepareStatement(sql); ps.setString(1, newStu.getName()); ps.setInt(2, newStu.getAge()); ps.setLong(3, newStu.getId()); //執行sql語句 ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 JdbcUtil.close(conn, ps, null); } } public Student get(Long id) { String sql = "SELECT * FROM s_student WHERE id = ? "; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //載入註冊驅動 //獲取連線物件 conn = JdbcUtil.getConn(); // 獲取語句物件 ps = conn.prepareStatement(sql); ps.setLong(1, id); // 執行SQL語句 rs = ps.executeQuery(); if (rs.next()) { Student stu = new Student(); Long sid = rs.getLong("id"); String name = rs.getString("name"); Integer age = rs.getInt("age"); stu.setId(sid); stu.setName(name); stu.setAge(age); return stu; } } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, ps, rs); } return null; } public List<Student> list() { List<Student> list = new ArrayList<>(); String sql = "SELECT * FROM s_student"; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //載入註冊驅動 //獲取連線物件 conn = JdbcUtil.getConn(); //獲取語句物件 ps = conn.prepareStatement(sql); //執行sql語句 rs = ps.executeQuery(sql); //查詢操作 while(rs.next()){ Student stu = new Student(); Long id = rs.getLong("id"); String name = rs.getString("name"); Integer age = rs.getInt("age"); stu.setName(name); stu.setId(id); stu.setAge(age); list.add(stu); } } catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtil.close(conn, ps, rs); } return list; } }
發現save,delete,update方法的程式碼只有sql不同,所以,把公共的程式碼提出來放在模板類中的update方法中,把sql作為引數傳到方法中。因為存在sql語句中的佔位符並且站位符的個數並不確定,可以採用可變引數進行傳參,把需要給站位符設定的站放在一個Object陣列中,作為引數傳到update方法中,在update方法中又把陣列中的值迭代出來賦給特定的sql語句
public void save(Student stu) { String sql = "INSERT INTO s_student(name,age) VALUES(?,?)"; JdbcTemplate.update(sql,stu.getName(),stu.getAge()); } public void delete(Long id) { String sql = "DELETE FROM s_student WHERE id = ?"; JdbcTemplate.update(sql, id); } public void update(Student newStu) { String sql = "UPDATE s_student SET name = ?,age = ? WHERE id = ?;"; JdbcTemplate.update(sql, newStu.getName(),newStu.getAge(),newStu.getId()); }
模板中的update方法:
/** * DML語句的操作的模板 * @param sql sql語句 :UPDATE INSERT DELETE * @param params sql語句中的站位符? 對應值的陣列 * @return 返回受影響的行數 */public static int update(String sql,Object...params){ Connection conn = null; PreparedStatement ps = null; try { //載入註冊驅動,獲取連線物件 conn = JdbcUtil.getConn(); ps = conn.prepareStatement(sql); // for(int i = 0; i < params.length; i++){ ps.setObject(i + 1, params[i]); } return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 JdbcUtil.close(conn, ps, null); } return 0; }
query的抽取有些麻煩,因為它會返回一個結果集,處理結果集的行為,不應該作為模板中的程式碼,而是應該交給給自的DAO來完成,因為給自的DAO才知道各自表的列有哪一些,作為模板肯定只有在模板中呼叫DAO中處理完成後的結果集,但是為了保證傳入query方法的引數是一致的,肯定需要定義一個規範,在程式中也就是定義一個介面,把這個介面就叫做結果集處理器,每一個DAO的實現類中要有一個處理結果的內部類,這個內部類去實現結果處理器介面,返回一個結果集供模板呼叫. 也就是,模板中query方法表面呼叫介面中的方法,實際呼叫的是各個DAO實現類中的結果集.這就是多型思想
//結果集處理器public interface IResultSetHandler<T> { T handle(ResultSet rs) throws Exception; }
學生結果集處理器 實現了結果處理器介面
public class StudentHandler implements IResultSetHandler<List<Student>>{ @Override public List<Student> handle(ResultSet rs) throws Exception { List<Student> list = new ArrayList<>(); while(rs.next()){ Student stu = new Student(); stu.setAge(rs.getInt("age")); stu.setId(rs.getLong("id")); stu.setName(rs.getString("name")); list.add(stu); } return list; } }
DAO實現類中的get方法和list方法變成了:
public Student get(Long id) { String sql = "SELECT * FROM s_student WHERE id = ? "; List<Student> list = JdbcTemplate.query(sql,new StudentHandler(), id); return list.size() == 1?list.get(0) : null; }public List<Student> list() { String sql = "SELECT * FROM s_student"; return JdbcTemplate.query(sql,new StudentHandler()); }
模板中的qurey方法:
//DQL語句的操作模板public static <T> T query(String sql,IResultSetHandler<T> ih,Object...params){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JdbcUtil.getConn(); //獲取語句物件 ps = conn.prepareStatement(sql); for(int i = 0; i < params.length; i++){ ps.setObject(i + 1, params[i]); } //執行sql語句 rs = ps.executeQuery(); //處理結果集 return ih.handle(rs); } catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtil.close(conn, ps, rs); } return null; }
上述qurey方法抽取還存在一個問題就是,每個DAO實現類都得實現介面編寫各自的結果處理器,如果DAO比較多,這個也就很麻煩了,能不能抽取值抽取一個更加通用的呢,那就得滿足一定的規範,比如可以透過內省機制可以完成,但是列名必須和JavaBean的屬性名相同。
public class BeanHandler<T> implements IResultSetHandler<T>{ private Class<T> classType = null; public BeanHandler(Class<T> classType){ this.classType = classType; } @Override public T handle(ResultSet rs) throws Exception { //建立對應類的物件 T obj = classType.newInstance(); if(rs.next()){ BeanInfo info = Introspector.getBeanInfo(classType,Object.class); PropertyDescriptor[] pds = info.getPropertyDescriptors(); for (PropertyDescriptor ps : pds) { String column = ps.getName(); Object val = rs.getObject(column); ps.getWriteMethod().invoke(obj,val); } } return obj; } }
public class BeanListHandler<T> implements IResultSetHandler<List<T>>{ private Class<T> classType = null; public BeanListHandler(Class<T> classType){ this.classType = classType; } @Override public List<T> handle(ResultSet rs) throws Exception { List<T> list = new ArrayList<>(); //建立物件 //獲取物件描述器 while(rs.next()){ T obj = classType.newInstance(); BeanInfo info = Introspector.getBeanInfo(classType,Object.class); PropertyDescriptor[] pds = info.getPropertyDescriptors(); for (PropertyDescriptor ps : pds) { //獲取物件的屬性名,屬性名和列名相同就呼叫setter方法把某一列的資料設定到物件中 String columnName = ps.getName(); Object val = rs.getObject(columnName); ps.getWriteMethod().invoke(obj, val); } list.add(obj); } return list; } }
這時候的DAO實現類中方法可以這樣來:
public Student get(Long id) { String sql = "SELECT * FROM s_student WHERE id = ? "; return JdbcTemplate.query(sql,new BeanHandler<>(Student.class), id); }public List<Student> list() { String sql = "SELECT * FROM s_student"; return JdbcTemplate.query(sql, new BeanListHandler<>(Student.class)); }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2041/viewspace-2817648/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JdbcTemplateJDBC
- SpringBoot使用JdbcTemplateSpring BootJDBC
- JdbcTemplate基礎JDBC
- JDBCTemplate--介紹JDBC
- Spring框架|整合JdbcTemplateSpring框架JDBC
- springboot整合使用JdbcTemplateSpring BootJDBC
- Spring 的 JdbcTemplate 和 JdbcDaoSupportSpringJDBC
- #Spring JdbcTemplate入門@FDDLCSpringJDBC
- day14-JdbcTemplate-01JDBC
- JdbcTemplate調儲存過程JDBC儲存過程
- Spring JdbcTemplate之使用詳解SpringJDBC
- Spring 系列之jdbcTemplate的使用SpringJDBC
- TRIZ——抽取原理·利弊
- [資訊抽取]基於ERNIE3.0的多對多資訊抽取演算法:屬性關係抽取演算法
- 評標專家的抽取時間, 提前多久抽取才合適?
- 資料上雲,應該選擇全量抽取還是增量抽取?
- 搞定實體識別、關係抽取、事件抽取,我用指標網路事件指標
- 註解與抽取基類
- [NLP] 知識抽取技術
- uniapp 隨機抽取影片播放APP隨機
- OGG的抽取程式合併
- spring下 -spring整體架構,JdbcTemplate筆記Spring架構JDBC筆記
- Spring04——Spring操作JdbcTemplate進行JDBC操作SpringJDBC
- Transwarp元件Trasporter工具資料抽取元件
- [20181217]ogg抽取日誌分析.txt
- sqoop條件抽取報錯distcpOOPTCP
- AMDU資料抽取案例一則
- 抽取思維(重構設計)
- 第二篇:SpringBoot2.x中使用JdbcTemplateSpring BootJDBC
- Spring Boot 2.x基礎教程:使用JdbcTemplate訪Spring BootJDBC
- 筆記53-Spring jdbcTemplate&宣告式事務筆記SpringJDBC
- 最佳化Extract抽取程式效能,解決OGG抽取日誌延遲 2017-11-12 1758
- MySQL、Oracle後設資料抽取分析MySqlOracle
- goldengate抽取程式延遲90小時Go
- spring-boot-route(七)整合jdbcTemplate運算元據庫SpringbootJDBC
- Datax離線資料抽取(MySQL--MySQL)MySql
- Datax離線資料抽取(Oracle--MySQL)OracleMySql
- Datax離線資料抽取(MySQL--Oracle)MySqlOracle