生成Java JDBC訪問代碼,從SQL文件

jopen 10年前發布 | 20K 次閱讀 JDBC Java開發

JDBC訪問數據庫

通過JDBC訪問數據庫,相信不少人都用過。比較辛苦,有很多的boilerplate。很多聰明的程序員也發現了這個問題,通過各種方式來解決這 個問題(當然,他們也為了解決另外的問題, boilerplate是其中之一),比如Hibernate,iBATIS,JdbcTemplate(Spring),等等。這幾種,各有各的優勢, 也有很多用戶。

最近在項目中,受Thrift,以及其它一些項目啟發,試著寫了一個程序,來自動生成JDBC的訪問代碼。

SQL,簡潔,表達力強

SQL,表達能力強,沒有多少boilerplate:

SELECT isbn, title, price, price * 0.06 AS sales_tax
FROM  Book WHERE price > 100.00 ORDER BY title limit 10;

程序:函數,參數,返回值

我們在寫程序時,可能價格是個參數,還需要支持分頁(limit, offset),返回的是List, 于是就是:

func list<Book> getBooksByPrice(float price, i32 limit, i32 offset) {
  SELECT isbn, title, price, price * 0.06 AS sales_tax
  FROM  Book WHERE price > :price ORDER BY title limit :limit, :offset;
}

這段話,表達是清楚的,并且沒有額外的“客套話”。 如果有一個程序,輸入是上面的code,生成的code是可以直接被調用的函數,將是理想情況。

java-jdbc

這里有個問題,Book未定義。當然,我們可以解析SQL語句,找到它來自Book表,繼而contact數據庫,找到Book表的metadata,能找到各個字段的數據類型, 就能定義Book了。如果這里面有Join的情況,會多聯系幾張表。 這樣引入了聯系數據庫的依賴,增加依賴一般是需要再三考慮的。另外,解析SQL,找出字段的來源去脈,推斷類型,不是一件簡單的工作。

但有個折中的辦法,引入一些冗余(為什么是冗余呢?因為這個Book定義的信息是可以推導出來的)

struct Book {
    string isbn
    string title
    float price
    float salesTax
}

雖加入了一些冗余,貌似還可以接受。

我試著用Python寫了這個程序java-jdbc,輸入是上面的代碼,輸出是Java代碼(函數)。

示例

運行命令

python java_jdbc.py --input example.sf --out gen-java

就會在 gen-java目錄生成訪問數據庫的代碼。其中輸入文件(example.sf):

namespace java me.shenfeng

struct Item {
    i32 id
    string name
}

// select
func Item getItemById(i32 id) {
    select * form item where id = :id
}
func list<Item> getItems(int limit, int offset) {
    select * from item limit :limit, :offset
}
func list<Item> getItems(list<i32> ids) {
    select * from item where id in (:ids) order by FIELD(id, :ids)
}

// insert, return generated primary key
func i32 saveItem(string name) {
    insert into item (name) value (:name)
}

// update
func void updateItem(i32 id, string newName) {
    update item set name = :newName where id = :id
}

// delete
func void deleteItemById(i32 id) {
    delete from item where id = :id
}

生成的API:

生成Java JDBC訪問代碼,從SQL文件

相比其它方案的優勢,缺點,以及以后的方向

相比Hibernate,iBATIS,JdbcTemplate(Spring),java-jdbc優點:

  1. 理解成本低,幾乎是self-explained。
  2. runtime零依賴,生成的code不依賴任何第三方庫
  3. 對join等支持良好,對各個數據庫的“特殊” 特性,“原生”支持。
  4. 維護方便。維護SQL,幾乎是最簡單的,SQL的文檔也很多。
  5. 實現簡單 (300多行Python code)

缺點:

  1. 有的同學不是很喜歡SQL
  2. 功能單一,有些挺實用的功能,比如cache機制,讀寫分離機制,并沒有支持

后面的方向嘛,由于這相當于定義了新的語言,可以通過擴展語言的方式,來擴展功能,比如

// 最多cache 10000,通過lru策略淘汰,每個cache時間,最多3600s。 TODO
@lru(size=10000, expire=3600s)
func list<Book> getBooksByPrice(float price, i32 limit, i32 offset) {
  SELECT isbn, title, price, price * 0.06 AS sales_tax
  FROM  Book WHERE price > :price ORDER BY title limit :limit, :offset;
}

</div>

原文鏈接: http://shenfeng.me/java-jdbc-generate-boilerplate.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!