在Java中键入Safe SQL
字符串,字符串,字符串
無論您使用的是JPA , MyBatis還是Spring Data JDBC之類的框架,最終都將SQL語句聲明為Java String。
這種方法的問題在于,您必須為每個語句編寫測試,以確保它甚至是有效的SQL。 沒有編譯時保證將執(zhí)行SQL語句。
擺脫弦樂!
嵌入式SQL
我于1995年開始在COBOL中的IBM大型機編程上進行專業(yè)軟件開發(fā)。 要訪問數(shù)據(jù)庫,我們使用了“嵌入式SQL”:
EXEC SQL SELECT lastname, firstname INTO :lastname, :firstname FROM employee WHERE id = :id 關于嵌入式SQL的最酷的事情是,預編譯器將檢查每個SQL語句,并且僅在編譯后的代碼有效的情況下對其進行檢查。
在下面您可以看到編譯步驟。 (來源: http : //www.redbooks.ibm.com/redbooks/pdfs/sg246435.pdf )
SQLJ
當我在2000年首次遇到Java和JDBC時,我很困惑,沒有類似的東西存在。 我發(fā)現(xiàn)有一個名為SQLJ的計劃始于1997年,但從未成功。 我不知道為什么,也許是因為這對于IDE廠商和預編譯器很難集成,而Java對Java來說并不常見。 至少編譯步驟類似于嵌入式SQL:
在比較JDBC和SQLJ時,我們可以看到與編寫的代碼量沒有太大區(qū)別,但是#sql之后的所有內(nèi)容都是類型安全的,因為預編譯器會檢查語法,就像JDBC一樣,其中可能包含一個String任何錯誤,該錯誤將在生產(chǎn)后期發(fā)生。
然后我找到了jOOQ!
十年前,盧卡斯·埃德(Lukas Eder)發(fā)行了jOOQ的第一個版本。 據(jù)該網(wǎng)站稱,jOOQ是“用Java編寫SQL的最簡單方法”
讓我們嘗試使用jOOQ編寫與上述相同的查詢:
List<EmployeeDTO> records = create .select(EMPLOYEE.LASTNAME, EMPLOYEE.FIRSTNAME, EMPLOYEE.SALARY) .from(EMPLOYEE) .where(EMPLOYEE.SALARY.between( 80000 , 100000 )) .fetchInto(EmployeeDTO. class );很酷,不是嗎? 是的-但是如何運作?
1.代碼生成器
jOOQ使用代碼生成器從數(shù)據(jù)庫對象生成Java類。
例如,這是jOOQ為表EMPLOYEE生成的類的摘錄:
public class Employee extends TableImpl<EmployeeRecord> { public static final Employee EMPLOYEE = new Employee(); public final TableField<EmployeeRecord, Integer> ID = createField( "ID" , org.jooq.impl.SQLDataType.INTEGER.nullable( false ).identity( true ), this , "" ); public final TableField<EmployeeRecord, String> LASTNAME = createField( "LASTNAME" , org.jooq.impl.SQLDataType.VARCHAR( 50 ).nullable( false ), this , "" ); public final TableField<EmployeeRecord, String> FIRSTNAME = createField( "FIRSTNAME" , org.jooq.impl.SQLDataType.VARCHAR( 50 ).nullable( false ), this , "" ); public final TableField<EmployeeRecord, Integer> SALARY = createField( "SALARY" , org.jooq.impl.SQLDataType.INTEGER, this , "" ); public final TableField<EmployeeRecord, Integer> DEPARTMENT_ID = createField( "DEPARTMENT_ID" , org.jooq.impl.SQLDataType.INTEGER.nullable( false ), this , "" ); public final TableField<EmployeeRecord, Integer> MANAGER_ID = createField( "MANAGER_ID" , org.jooq.impl.SQLDataType.INTEGER, this , "" ); }該表和所有列都有常量。 由于這些元數(shù)據(jù)類,因此無法在數(shù)據(jù)庫中不存在的SQL語句中使用類型。 并且由于您可以每次生成元數(shù)據(jù),因此如果發(fā)生重大更改,數(shù)據(jù)庫模型更改將不會編譯您的代碼。
以后的文章中將介紹如何配置生成器以及可能的生成器輸入格式。 (敬請關注)
2.領域特定語言
jOOQ的第二部分是DSL(特定于域的語言),它允許用Java編寫SQL代碼。
與String中的SQL相比,DSL迫使我編寫有效的SQL!
例子
因此,讓我們來看更多示例。 示例基于此數(shù)據(jù)模型:
插
dsl.insertInto(DEPARTMENT) .columns(DEPARTMENT.NAME) .values( "HR" ) .execute();選擇
dsl.select(DEPARTMENT.NAME) .from(DEPARTMENT) .where(DEPARTMENT.NAME.eq( "IT" )) .fetchOne();更新資料
dsl.update(DEPARTMENT) .set(DEPARTMENT.NAME, "IT2" ) .where(DEPARTMENT.ID.eq(departmentId)) .execute();刪除
dsl.deleteFrom(EMPLOYEE) .where(EMPLOYEE.ID.eq(employeeId)) .execute();下一步是什么?
那只是一個簡短的介紹。 在下一篇博客文章中,我們將更深入地了解jOOQ提供的所有功能。
同時,您可以在此處簽出代碼: https : //github.com/simasch/jooq-hr
翻譯自: https://www.javacodegeeks.com/2019/12/type-safe-sql-in-java.html
總結(jié)
以上是生活随笔為你收集整理的在Java中键入Safe SQL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux内核最新版本(linux 内核
- 下一篇: 设计模式 生成器_生成器设计模式的应用