有的時候我們數(shù)據(jù)庫設(shè)計可能不會完全和代碼語言一致,比如我們會在數(shù)據(jù)庫的每一張表前面加上一個特定的前綴用于區(qū)分,在BeetlSQL中將代碼Pojo的名稱和數(shù)據(jù)庫Table名稱對應起來是使用NameConversion來轉(zhuǎn)換的,BeetlSQL內(nèi)置了DefaultNameConversion、UnderlinedNameConversion和JPANameConversion等轉(zhuǎn)換器基本上可以滿足絕大部分的要求的,今天就來給大家演示一下如何自定義NameConversion。
前言
要了解本文的內(nèi)容,首先你需要先了解Beetl和BeetlSQL這兩個項目,它們是來自于國人@閑·大賦嘔心瀝血精心打造的Java模板引擎和Java數(shù)據(jù)庫全功能Dao,而且目前官方已經(jīng)提供了Beetl和BeetlSQL與市面上各種主流MVC框架的整合方案
我不敢說Beetl比JSP、FreeMarker、Velocity等大家熟知的一些模板引擎怎么怎么的好,但是我想說以我個人的使用經(jīng)歷來做對比,Beetl絕對不會比它們差,BeetlSQL更是不會比Hibernate和MyBatis等差
如果有興趣想了解一下Beetl和BeetlSQL,可以訪問Beetl官方論壇查閱詳情。
何不給Beetl一個機會來證明Beetl自己,更是給你自己一個學習工作嘗試的機會,說不定你就和我一樣一不留神就愛上了它。
正文
本文討論的是在使用BeetlSQL自動生成Pojo對象時,通過自定義轉(zhuǎn)換器去除映射表名前綴的問題。
先看一組開發(fā)遇到的情況:
假定當前有個項目beetl在數(shù)據(jù)庫設(shè)計的時候,所有的表名都有一個項目前綴bt_,即所有的表都以bt_開頭,如bt_user、bt_role、bt_user_role,看到這樣的表名設(shè)計我們可能第一想到的是使用UnderlinedNameConversion來進行轉(zhuǎn)化,于是乎:
bt_user-> BtUser
bt_role -> BtRole
bt_user_role -> BtUserRole
相信很多人肯定和我一樣是不能接受這樣的命名的,所以我們需要自己定義一個NameConversion來進行轉(zhuǎn)換,去除掉Table生成Pojo時自動加上的Bt前綴
NameConversion中核心的幾個方法getPropertyName、getColName、getTableName、getClassName,根據(jù)方法名和參數(shù)很容易理解
因此我們只需要根據(jù)我們自己的實際需求重新實現(xiàn)一個NameConversion將表名轉(zhuǎn)類名、類名轉(zhuǎn)表名的方法重新實現(xiàn)以下即可。
具體做法:首先我們新建一個類繼承自DefaultNameConversion類,分別重寫getClassName和getTableName兩個方法,最后在我們的項目中啟用自己寫的Conversion
@Override
@Overridepublic String getTableName(Class<?> c) { //遵循BeetlSQL規(guī)范,@Table擁有最高優(yōu)先級 Table table = (Table)c.getAnnotation(Table.class); if(table!=null){ return table.name(); } //UserRole -> user_role String tableName = StringKit.enCodeUnderlined(c.getSimpleName()); //user_role -> bt_user_role return "bt_"+tableName; }@Overridepublic String getClassName(String tableName){ //假定所有表都是以bt_開頭 //bt_user_role -> user_role tableName = tableName.substring(tableName.indexOf("_")+1); //user_role -> userRole String clsName = StringKit.deCodeUnderlined(tableName); //userRole -> UserRole return StringKit.toUpperCaseFirstOne(clsName); }
就這樣輕松的完成的整個數(shù)據(jù)庫的表名去前綴。
事與愿違?。。?往往我們可能還會遇到更特殊的情況,下面讓我們再來看一組開發(fā)可能遇到的情況:
當前有一個項目,里面有一些用戶的數(shù)據(jù)表(如User),后臺管理的數(shù)據(jù)表(如Admin)和以前用戶與后臺公共的數(shù)據(jù)表(如City),然后在開發(fā)時為了做區(qū)分,分別給不同的功能模塊的表加上了不同的前綴,最后我們的表名可能是:usr_user、mgr_admin和base_city這樣的形式,這時候我們再使用上面的方式統(tǒng)一去前綴再統(tǒng)一加前綴肯定是行不通的,畢竟前綴不一樣你去掉前綴后是很難直接還原的。
最初我遇到這樣的問題,第一想法是,讓BeetlSQL反向生成Pojo的時候,去除前綴然后自動給所有的Pojo加上@Table的注解,例如例子中的usr_user、mgr_admin和base_city三張表 最后可能生成如下形式:
usr_user -> @Table(name="usr_user") User
mgr_admin -> @Table(name="mgr_admin") Admin
base_city -> @Table(name="base_city") City
理想是豐滿的,現(xiàn)實是骨感的。在QQ上與作者溝通遇到這種情況時的解決方案時發(fā)現(xiàn)可能會出現(xiàn)這樣的情況: 前臺用戶使用的數(shù)據(jù)表可能是 usr_user,而后臺管理員也屬于用戶呀,因此可能后臺管理員的數(shù)據(jù)表為mgr_user,最后這樣會導致兩個類沖突了,生成代碼的時候可能會被覆蓋一個類,是有問題的。好在機智如我~遇到這樣的根據(jù)功能模塊給不同的表加上不同的前綴,我們在Java程序開發(fā)時也經(jīng)常會使用不同的包名來區(qū)分不同的模塊,我可以將不同前綴的實體放到對應的包下面,還原表名的時候讀取一下包名即可反向解析出表名,下面是我的具體實現(xiàn):
@Overridepublic String getClassName(String tableName){ //為了安全起見,做了個判斷,理論上項目數(shù)據(jù)庫設(shè)計好了應該是無需判斷直接截取所有前綴 //usr_user_role -> user_role if(tableName.matches("^(usr_|base_|mgr_).*")){ tableName = tableName.substring(tableName.indexOf("_")+1); } //user_role -> UserRole String clsName = StringKit.deCodeUnderlined(tableName); return StringKit.toUpperCaseFirstOne(clsName); }@Overridepublic String getTableName(Class<?> c) { Table table = (Table)c.getAnnotation(Table.class); if(table!=null){ return table.name(); } //獲取Package 最后一層 xxx.pojo.usr -> Usr String pkg = c.getPackage().getName(); pkg = pkg.substring(pkg.lastIndexOf(".")+1); pkg = Character.toUpperCase(pkg.charAt(0))+pkg.substring(1); //Usr+User -> UsrUser -> usr_user return StringKit.enCodeUnderlined(pkg+c.getSimpleName()); }
然后在使用BeetlSQL反向生成Pojo的時候,使用Filter將數(shù)據(jù)表分門別類的生成到不同的包下面
//記得初始化SQLManager時要使用自己寫好的NameConvertionSQLManager sql = initSQLManager(); GenConfig config = new GenConfig(); sql.genALL("xxxx.pojo.usr", config, new GenFilter(){ @Override public boolean accept(String tableName) { return tableName.startsWith("usr_"); } }); sql.genALL("xxxx.pojo.mgr", config, new GenFilter(){ @Override public boolean accept(String tableName) { return tableName.startsWith("mgr_"); } }); sql.genALL("xxxx.pojo.base", config, new GenFilter(){ @Override public boolean accept(String tableName) { return tableName.startsWith("base_"); } });
最終會在項目中會生成以下Pojo
usr_user -> xxxx.pojo.usr.User.java
mgr_admin -> xxxx.pojo.mgr.Admin.java
base_city -> xxxx.pojo.base.City.java
即便是有類名沖突的,因為在不同的包下,所以也不會影響
就這樣一次輕松而又愉快的BeetlSQL自定義去除Pojo和表前綴被解決啦~
最后
之前所有項目的開發(fā)都是Jsp,幾乎沒使用過其他第三方模板庫,因為一次誤打誤撞讓我認識了Beetl,它的輕巧,它獨特的語法都深深的吸引了我,因為Beetl又讓我認識了BeetlSQL,抱著試一試的心態(tài)嘗試過之后總有一種把當前項目(使用的Hibernate)推倒重來的沖動,雖然最后因為項目的工程量和工期原因,當前的這個項目最終還是使用了Hibernate,但是我可以確定的是,在以后的開發(fā)道路上,如果允許,如果沒有能讓我更心動的通用Dao,BeetlSQL將會是我不二的選擇。
今天在這里分享這篇自定義NameConvertion的功能,其實并沒有多少技術(shù)含量,更多的是想做一次簡單的推廣,讓更多人知道Beetl,讓更多人愛上Beetl~

熱AI工具

Undress AI Tool
免費脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動的應用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機

Video Face Swap
使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級代碼編輯軟件(SublimeText3)