总结一下Java中SQL的九种写法
生活随笔
收集整理的這篇文章主要介紹了
总结一下Java中SQL的九种写法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
因為在做持久層工具開發,現總結一下各種SQL的寫法,也算是清晰一下自已的思路:
第一種寫法
public void someMethod(){
try
Connection conn=...;
conn.setAutoCommit(false);
PreparedStatement pst=...;
ResultSet rs= executeSomeSql("some sql...");
conn.commit();
} catch (SQLException ex) {
doSomething();
} finally {
close(rs);
close(pst);
close(conn)
}
最基礎的JDBC用法,從connectin的獲取,事務的開啟、提交,rs、st、connection的關閉全部照顧到
優點:100%掌控所有細節。
缺點:過分繁瑣,不推薦業務開發中使用
支持第一種寫法的工具類:JDK自帶。
第二種寫法
public void someMethod(Connection conn) throws SQLException {
queryRunner.executeSQL(conn, "some sql...",參數1, 參數2...);
}
將connection作為參數傳遞, 業務方法不再負責connection的關閉。
優點:業務方法可以簡化到一條語句,極大簡化了編程。
缺點:必須另外有一個總的方法進行導常處理和關閉connection,connection作為業務方法的參數傳入是對業務方法的入侵。
支持第二種寫法的工具類:DbUtils。
第三種寫法
QueryRunner queryRunner=new QueryRunner(dataSource);
public void someMethod() throws SQLException {
queryRunner.executeSQL("some sql...",參數1, 參數2...);
}
不再將connection作為參數傳遞, 工具類構造時將DataSource實例注入,SQL方法完成后Connection自動關閉。
優點:業務方法可以簡化成一條語句,沒有connection參數入侵業務方法。
缺點:如沒有第三方服務支持,事務不太好控制,SQLException異常的拋出也是一種入侵,還是需要另一個方法來捕獲。
代表作:DbUtils。
第四種寫法
DbPro dbPro=new DbPro(dataSource);
public void someMethod(){
dbPro.executeSQL("some sql...",參數1, 參數2...);
}
業務方法沒有Connection參數傳入,也不會拋出SQLException異常,工具類將SqlException轉化為運行時異常拋出。
優點:業務方法沒有受到入侵(嚴格來說dbPro變量的存在也是對業務方法的一種極輕度的入侵,影響業務方法的可移植性),無須關心異常,運行時異常通常不必處理,由事務服務捕獲并回滾。
缺點:無明顯缺點,但是要引入IOC/AOP工具如Spring等,以捕獲切面的方式實現對異常處理、事務處理及Connection的關閉的支持。
代表作:Spring-JDBC、DbUtils-Pro
以上是從對connection關閉、異常處理和事務處理的角度來看的,從以下寫法將開始研究對SQL本身寫法的優化:
第五種寫法
DbPro dbPro=new DbPro(dataSource);
public void someMethod(){
dbPro.executeSQL("sql piece1",param0(參數1),"sql piece2", param(參數2),"sql piece3",param(參數3)...);
}
將參數利用ThreadLocal暫存,從而可以將參數織入到SQL的任意位置,詳見"一種將SQL包裝成PrepraredStatement的方法"([url]http://www.iteye.com/topic/1145415[/url]),
優點:1)如果字段名用Java方法或常量代替,則可以實現讓普通的SQL支持重構。
2)參數多的SQL,可以保證占位符與實際參數相鄰,利于維護。例如下面這種寫法,比起傳統的JdbcTemplate將所有參數放在方法未尾傳遞的方式,在可維護性上要好很多:
DbPro.execute("update user set", //
" username=?", param0("Bill"), //
",age=?", param("23"), //
",address=", question("Tianjing"), //
" where id=", question(5));
缺點:重復的參數也必須重復注入; ThreadLocal變量有可能互相干攏,例如不能在一個SQL方法中嵌套另一個SQL調用;
代表作:DbUtils-Pro (或jSqlBox, 其內核基于DbUtils-Pro)
第六種寫法
public void someMethod(){
put0("name","張三");
user.setAddress("BeiJing");
put("user",user);
dbPro.executeSQL("update users set name=#{name}, address=#{user.address}");
或 dbPro.executeSQL(findSQL("someSqlID"));
}
利用模板來統一存放SQL,模板的形式可以為XML、文本或Java字符串、Java Annoation、JVM語言如Groovy甚至Java注釋(見[url]https://my.oschina.net/drinkjava2/blog/892309)[/url]),另外使用模板也可用第5種方法介紹過的利用ThreadLocal賦值。
優點:便于統一管理SQL,尤其是一些長SQL
缺點:模板不支持重構,參數的賦值和實際的SQL有時存放在兩個文件里,而IDE又不支持導航定位,維護不方便。占位符的存在和賦值要多打幾個字。
代表作:MyBatis, BeetlSql, DbUtils-Pro, NamedParameterJdbcTemplate
以下寫法開始,引入了ORM概念,從SQL角度來看,ORM也可看成一種寫SQL的寫法。ORM主要分兩大部分:1)Java Bean與數據庫表的映射 2)Bean之間關聯關系與數據庫表關聯關系的映射
ORM框架林林總總:
從功能來區分,有些簡單到只有Bean到數據表的映射如Memory;有些只支持單向的關聯映射如MyBatis/BeetlSql/jSqlBox, 有些是全功能的支持復雜的對象-數據庫雙向關聯關系映射如Hibernate,
從是否支持配置來區分,有些是零配置的(如Memory/jFinal-Dao/DbUtils),映射關系靠命名約定來保證, 有些是固定配置的,一旦配置好就不能再變動(MyBatis/Hibernate/JPA/BeetlSQL)。有些支持運行期動態調整配置(如jSqlBox)。
從配置方式來區分,有寫在XML中(MyBatis),有寫在注解中(Hibernate/JPA/BeetlSQL),有寫在Java方法里(jSqlBox)
第七種寫法
public void someMethod(){
Session session = getSessionFromSomeWhere();
User user = new user();
user.setName("張三");
session.save(user);
}
優點:CRUD操作非常方便
缺點:對復雜SQL無能為力;session變量的存在對業務方法是一種輕度入侵,當session的功能設計的很復雜,方法很多時,就變成了重度入侵,嚴重影響業務方法的可移植性。
代表作:Hibernate, MyBatis, BeetlSql
第八種寫法
public void someMethod(){
User user = new user();
user.setName("張三");
user.save();
}
又被稱為ActiveRecord模式,業務方法中沒有session變量出現,
優點:CRUD操作非常方便, 業務方法更簡煉
缺點: 對復雜SQL無能為力;Java8以下要實現這種寫法,必須讓實體類繼承于一個基類,占用了唯一的單繼承,這也是一種(大多數情況下無關緊要的)入侵。Java8情況要好一些,只需要聲明實現接口即可。
代表作:jFinal-Dao, jSqlBox 以及所有基于ActiveRecord模式的持久層工具
第九類寫法
嚴格來說,這不是一種寫法,而是一大類五花八門的寫法,它往往是專有的,僅適用于各自的框架,例如Hibernate的HQL語言,Hibernate以及Nutz的用Java方法來代替SQL語法,Spring Boots用方法名代替SQL,各種模板對SQL語法的擴充,jSqlBox的利用ThreadLocal暫存映射配置等,如果你看到什么新奇的SQL寫法,都歸到這一大類吧,第九類寫法并不都優于前面8種寫法,只是不太好歸類而已,甚至個人認為有些是反模式,如HQL和用Java方法代替SQL語法等。
具體在開發中個人優先推薦使用第5、6、8種寫法。
另外文中提到的DbUtils-Pro還處于開發階段,它是一個繼承于DbUtils的小項目,歡迎有興趣者加入。
第一種寫法
public void someMethod(){
try
Connection conn=...;
conn.setAutoCommit(false);
PreparedStatement pst=...;
ResultSet rs= executeSomeSql("some sql...");
conn.commit();
} catch (SQLException ex) {
doSomething();
} finally {
close(rs);
close(pst);
close(conn)
}
最基礎的JDBC用法,從connectin的獲取,事務的開啟、提交,rs、st、connection的關閉全部照顧到
優點:100%掌控所有細節。
缺點:過分繁瑣,不推薦業務開發中使用
支持第一種寫法的工具類:JDK自帶。
第二種寫法
public void someMethod(Connection conn) throws SQLException {
queryRunner.executeSQL(conn, "some sql...",參數1, 參數2...);
}
將connection作為參數傳遞, 業務方法不再負責connection的關閉。
優點:業務方法可以簡化到一條語句,極大簡化了編程。
缺點:必須另外有一個總的方法進行導常處理和關閉connection,connection作為業務方法的參數傳入是對業務方法的入侵。
支持第二種寫法的工具類:DbUtils。
第三種寫法
QueryRunner queryRunner=new QueryRunner(dataSource);
public void someMethod() throws SQLException {
queryRunner.executeSQL("some sql...",參數1, 參數2...);
}
不再將connection作為參數傳遞, 工具類構造時將DataSource實例注入,SQL方法完成后Connection自動關閉。
優點:業務方法可以簡化成一條語句,沒有connection參數入侵業務方法。
缺點:如沒有第三方服務支持,事務不太好控制,SQLException異常的拋出也是一種入侵,還是需要另一個方法來捕獲。
代表作:DbUtils。
第四種寫法
DbPro dbPro=new DbPro(dataSource);
public void someMethod(){
dbPro.executeSQL("some sql...",參數1, 參數2...);
}
業務方法沒有Connection參數傳入,也不會拋出SQLException異常,工具類將SqlException轉化為運行時異常拋出。
優點:業務方法沒有受到入侵(嚴格來說dbPro變量的存在也是對業務方法的一種極輕度的入侵,影響業務方法的可移植性),無須關心異常,運行時異常通常不必處理,由事務服務捕獲并回滾。
缺點:無明顯缺點,但是要引入IOC/AOP工具如Spring等,以捕獲切面的方式實現對異常處理、事務處理及Connection的關閉的支持。
代表作:Spring-JDBC、DbUtils-Pro
以上是從對connection關閉、異常處理和事務處理的角度來看的,從以下寫法將開始研究對SQL本身寫法的優化:
第五種寫法
DbPro dbPro=new DbPro(dataSource);
public void someMethod(){
dbPro.executeSQL("sql piece1",param0(參數1),"sql piece2", param(參數2),"sql piece3",param(參數3)...);
}
將參數利用ThreadLocal暫存,從而可以將參數織入到SQL的任意位置,詳見"一種將SQL包裝成PrepraredStatement的方法"([url]http://www.iteye.com/topic/1145415[/url]),
優點:1)如果字段名用Java方法或常量代替,則可以實現讓普通的SQL支持重構。
2)參數多的SQL,可以保證占位符與實際參數相鄰,利于維護。例如下面這種寫法,比起傳統的JdbcTemplate將所有參數放在方法未尾傳遞的方式,在可維護性上要好很多:
DbPro.execute("update user set", //
" username=?", param0("Bill"), //
",age=?", param("23"), //
",address=", question("Tianjing"), //
" where id=", question(5));
缺點:重復的參數也必須重復注入; ThreadLocal變量有可能互相干攏,例如不能在一個SQL方法中嵌套另一個SQL調用;
代表作:DbUtils-Pro (或jSqlBox, 其內核基于DbUtils-Pro)
第六種寫法
public void someMethod(){
put0("name","張三");
user.setAddress("BeiJing");
put("user",user);
dbPro.executeSQL("update users set name=#{name}, address=#{user.address}");
或 dbPro.executeSQL(findSQL("someSqlID"));
}
利用模板來統一存放SQL,模板的形式可以為XML、文本或Java字符串、Java Annoation、JVM語言如Groovy甚至Java注釋(見[url]https://my.oschina.net/drinkjava2/blog/892309)[/url]),另外使用模板也可用第5種方法介紹過的利用ThreadLocal賦值。
優點:便于統一管理SQL,尤其是一些長SQL
缺點:模板不支持重構,參數的賦值和實際的SQL有時存放在兩個文件里,而IDE又不支持導航定位,維護不方便。占位符的存在和賦值要多打幾個字。
代表作:MyBatis, BeetlSql, DbUtils-Pro, NamedParameterJdbcTemplate
以下寫法開始,引入了ORM概念,從SQL角度來看,ORM也可看成一種寫SQL的寫法。ORM主要分兩大部分:1)Java Bean與數據庫表的映射 2)Bean之間關聯關系與數據庫表關聯關系的映射
ORM框架林林總總:
從功能來區分,有些簡單到只有Bean到數據表的映射如Memory;有些只支持單向的關聯映射如MyBatis/BeetlSql/jSqlBox, 有些是全功能的支持復雜的對象-數據庫雙向關聯關系映射如Hibernate,
從是否支持配置來區分,有些是零配置的(如Memory/jFinal-Dao/DbUtils),映射關系靠命名約定來保證, 有些是固定配置的,一旦配置好就不能再變動(MyBatis/Hibernate/JPA/BeetlSQL)。有些支持運行期動態調整配置(如jSqlBox)。
從配置方式來區分,有寫在XML中(MyBatis),有寫在注解中(Hibernate/JPA/BeetlSQL),有寫在Java方法里(jSqlBox)
第七種寫法
public void someMethod(){
Session session = getSessionFromSomeWhere();
User user = new user();
user.setName("張三");
session.save(user);
}
優點:CRUD操作非常方便
缺點:對復雜SQL無能為力;session變量的存在對業務方法是一種輕度入侵,當session的功能設計的很復雜,方法很多時,就變成了重度入侵,嚴重影響業務方法的可移植性。
代表作:Hibernate, MyBatis, BeetlSql
第八種寫法
public void someMethod(){
User user = new user();
user.setName("張三");
user.save();
}
又被稱為ActiveRecord模式,業務方法中沒有session變量出現,
優點:CRUD操作非常方便, 業務方法更簡煉
缺點: 對復雜SQL無能為力;Java8以下要實現這種寫法,必須讓實體類繼承于一個基類,占用了唯一的單繼承,這也是一種(大多數情況下無關緊要的)入侵。Java8情況要好一些,只需要聲明實現接口即可。
代表作:jFinal-Dao, jSqlBox 以及所有基于ActiveRecord模式的持久層工具
第九類寫法
嚴格來說,這不是一種寫法,而是一大類五花八門的寫法,它往往是專有的,僅適用于各自的框架,例如Hibernate的HQL語言,Hibernate以及Nutz的用Java方法來代替SQL語法,Spring Boots用方法名代替SQL,各種模板對SQL語法的擴充,jSqlBox的利用ThreadLocal暫存映射配置等,如果你看到什么新奇的SQL寫法,都歸到這一大類吧,第九類寫法并不都優于前面8種寫法,只是不太好歸類而已,甚至個人認為有些是反模式,如HQL和用Java方法代替SQL語法等。
具體在開發中個人優先推薦使用第5、6、8種寫法。
另外文中提到的DbUtils-Pro還處于開發階段,它是一個繼承于DbUtils的小項目,歡迎有興趣者加入。
總結
以上是生活随笔為你收集整理的总结一下Java中SQL的九种写法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HttpClient下载
- 下一篇: neovim内置lsp实现Java语言补