Foxnic-SQL (5) —— 創(chuàng)建與初始化DAO
DAO
DAO 對象是 Foxnic-SQL 執(zhí)行語句并返回結(jié)果的核心對象。它包含了眾多方法,包括語句的執(zhí)行、查詢、序列、存儲過程,元數(shù)據(jù)等。
本文中的示例代碼均可在 https://gitee.com/LeeFJ/foxnic-samples 項目中找到。
創(chuàng)建與初始化 DAO 只要提供數(shù)據(jù)庫連接信息即可,示例代碼如下:
/**
* 創(chuàng)建 DAO 對象
* */
private DAO createDAO(String driverName,String url,String userName,String passwd) {
? ? // 從連接字符串識別數(shù)據(jù)庫類型
? ? DBType dbType=DBType.parseFromURL(url);
? ? // 創(chuàng)建數(shù)據(jù)源
? ? DruidDataSource dataSource = new DruidDataSource();
? ? dataSource.setDriverClassName(driverName);
? ? dataSource.setUrl(url);
? ? dataSource.setUsername(userName);
? ? dataSource.setPassword(passwd);
? ? // mysql 關(guān)閉,Oracle 建議開啟
? ? if(dbType==DBType.ORACLE) {
? ? ? ? dataSource.setPoolPreparedStatements(true);
? ? }
? ? // 通過 DAOBuilder 創(chuàng)建 DAO 對象
? ? DAOBuilder builder=new DAOBuilder();
? ? try {
? ? ? ? dao=builder.datasource(dataSource).build();
? ? ? ? // 設(shè)置全局方言
? ? ? ? GlobalSettings.DEFAULT_SQL_DIALECT=this.dao.getSQLDialect();
? ? ? ? // 設(shè)置數(shù)據(jù)庫規(guī)約
? ? ? ? dao.setDBTreaty(getDBTreaty());
? ? ? ? // 設(shè)置關(guān)系管理器
? ? ? ? dao.setRelationManager(new DemoRelationManager());
? ? ? ? //設(shè)置緩存
? ? ? ? FoxnicDataCacheManager cacheManager=new FoxnicDataCacheManager();
? ? ? ? CacheProperties cacheProperties=new CacheProperties(SpringUtil.getEnvProperties("foxnic.cache"));
? ? ? ? cacheManager.setCacheProperties(cacheProperties);
? ? ? ? cacheManager.setRelationManager(dao.getRelationManager());
? ? ? ? dao.setDataCacheManager(cacheManager);
? ? ? ? // 設(shè)置SQL打印
? ? ? ? dao.setPrintSQL(true);
? ? ? ? dao.setPrintSQLSimple(true);
? ? ? ? dao.setPrintSQLCallstack(true);
? ? ? ? return dao;
? ? } catch (Exception e) {
? ? ? ? Logger.error("創(chuàng)建DAO錯誤",e);
? ? ? ? return null;
? ? }
}
在上面的代碼中,首先通過數(shù)據(jù)庫連接信息創(chuàng)建了數(shù)據(jù)源 DataSource 對象,例子中使用的是 DruidDataSource ,大家也可以按照自己的喜好選擇數(shù)據(jù)源。然后是使用 DAOBuilder 創(chuàng)建 DAO。
GlobalSettings.DEFAULT_SQL_DIALECT 指定了默認(rèn)的SQL方言。默認(rèn)情況下為MySQL,如果SQL對象已經(jīng)關(guān)聯(lián)了DAO,則不使用全局方言,而是使用數(shù)據(jù)庫的本地SQL方言。
接著,為DAO對象設(shè)置 DBTreaty 數(shù)據(jù)庫規(guī)約對象,DBTreaty 主要是指定一些數(shù)據(jù)庫中約定俗成的東西,后面我們詳細(xì)講解。
后面是為 DAO 設(shè)置管理管理器和緩存管理器,這兩個我們在這里也不做展開,在后面的章節(jié)中我們再詳細(xì)介紹。最后,設(shè)置SQL打印日志的幾個選項,返回 DAO 對象即可。
下面,我們測試一下 DAO 是否可用:
/**
* DAO 查詢示例
* */
public static void demo_1() {
? ? // 通過 DBInstance 拿到 DAO 對象
? ? DAO dao=DBInstance.DEFAULT.dao();
? ? // 執(zhí)行查詢
? ? Integer value = dao.queryInteger("select ?",9090);
? ? // 輸出結(jié)果
? ? System.out.println("value = "+value);
? ? // 輸出 value = 9090
}
配置 DBTreaty
Foxnic-SQL中專抽象了一個概念,叫做數(shù)據(jù)庫規(guī)約(DBTreaty),它的作用是統(tǒng)一數(shù)據(jù)庫中通用字段的命名規(guī)范,通用值的取值規(guī)范等。
(1) 規(guī)范字段
創(chuàng)建人ID:默認(rèn)字段 create_by,規(guī)范創(chuàng)建人ID字段,使程序在插入時自動設(shè)置改值
創(chuàng)建時間:默認(rèn)字段 create_time,規(guī)范創(chuàng)建時間字段,使程序在插入時自動設(shè)置改值
更新人ID:默認(rèn)字段 update_by,同上,以此類推。
更新時間:默認(rèn)字段 update_time,同上,以此類推。
邏輯刪字段:默認(rèn)字段 deleted,同上,以此類推。
刪除人ID:默認(rèn)字段 delete_by,同上,以此類推。
刪除時間:默認(rèn)字段 delete_time,同上,以此類推。
數(shù)據(jù)版本:默認(rèn)字段 version_num,同上,以此類推。
租戶ID:默認(rèn)字段:tenant_id,同上,以此類推。
(2) 規(guī)范值以及值類型
邏輯值:用于統(tǒng)一數(shù)據(jù)庫中 true/false 邏輯值的實際存儲值,方便程序統(tǒng)一處理。
UserId值類型:用于規(guī)范創(chuàng)建人ID、更新人ID、刪除人ID等字段的值類型,方便程序處理。
(3)?輔助方法
SubjectHandler:用于返回當(dāng)前登錄會話對象。
LoginUserIdHandler:用于返回當(dāng)前登錄賬戶ID
TenantIdHandler:用于返回當(dāng)前登錄賬戶的租戶ID
這里需要特別說明的是 DBTreaty 并未對主鍵字段的名稱和類型做約定,主要考慮主鍵字段的命名未必需要統(tǒng)一(當(dāng)然,最好也能統(tǒng)一命名),而且有些情況下還存在聯(lián)合主鍵,所以主鍵規(guī)約暫不納入 DBTreaty 范圍內(nèi)。
以下是創(chuàng)建 DBTreaty 的示例代碼:
/**
* 創(chuàng)建一個符合項目設(shè)計的數(shù)據(jù)庫規(guī)約對象
* */
public DBTreaty getDBTreaty() {
? ? DBTreaty dbTreaty=new DBTreaty();
? ? // 設(shè)置是否在沒有 where 時可以刪除數(shù)據(jù)
? ? dbTreaty.setAllowDeleteWithoutWhere(false);
? ? // 設(shè)置是否在沒有 where 時可以更新數(shù)據(jù)
? ? dbTreaty.setAllowUpdateWithoutWhere(false);
? ? // 設(shè)置賬戶ID字段的類型
? ? dbTreaty.setUserIdDataType(DBDataType.STRING);
? ? // 設(shè)置租戶ID字段名
? ? dbTreaty.setTenantIdField("tenant_id");
? ? // 設(shè)置創(chuàng)建時間字段名
? ? dbTreaty.setCreateTimeField("create_time");
? ? // 設(shè)置創(chuàng)建人ID字段名
? ? dbTreaty.setCreateUserIdField("create_by");
? ? dbTreaty.setUpdateTimeField("update_time");
? ? dbTreaty.setUpdateUserIdField("update_by");
? ? dbTreaty.setDeletedField("deleted");
? ? dbTreaty.setDeleteTimeField("delete_time");
? ? dbTreaty.setDeleteUserIdField("delete_by");
? ? dbTreaty.setVersionField("version");
? ? // 設(shè)置是否對邏輯值進(jìn)行轉(zhuǎn)換,建議 false
? ? dbTreaty.setAutoCastLogicField(false);
? ? // 設(shè)置 false 對應(yīng)的數(shù)據(jù)庫值
? ? dbTreaty.setFalseValue(0);
? ? // 設(shè)置 true 對應(yīng)的數(shù)據(jù)庫值
? ? dbTreaty.setTrueValue(1);
? ? // 設(shè)置獲取當(dāng)前用戶的函數(shù)
? ? dbTreaty.setSubjectHandler(()->{
? ? ? ? return null;
? ? });
? ? // 設(shè)置獲取當(dāng)前登錄賬戶ID的函數(shù)
? ? dbTreaty.setLoginUserIdHandler(()->{
? ? ? ? return "leefj";
? ? });
? ? // 設(shè)置獲取當(dāng)前登錄賬戶的租戶ID的函數(shù)
? ? dbTreaty.setTenantIdHandler(()->{
? ? ? ? return "T001";
? ? });
? ? //
? ? return dbTreaty;
}
DBTreaty 的某些特性會在執(zhí)行層面體現(xiàn),還有一部分特性需要引入 Service 層才能體現(xiàn);例如,setAllowDeleteWithoutWhere 的控制,就可以在執(zhí)行時體現(xiàn),但創(chuàng)建人ID、創(chuàng)建時間等字段的自動填充,是需要引入 Service 層的,關(guān)于這方面的內(nèi)容,我們在后面繼續(xù)介紹。
/**
* DAO 刪除校驗實例 , 在? DBTreaty.setAllowDeleteWithoutWhere 控制。
* */
public static void demo_2() {
? ? // 通過 DBInstance 拿到 DAO 對象
? ? DAO dao=DBInstance.DEFAULT.dao();
? ? // 執(zhí)行查詢
? ? dao.execute("delete from mytable");
? ? // 拋出異常 : 當(dāng)前執(zhí)行的語句 delete from mytable , 缺少 where 條件
}
小結(jié)
本節(jié)我們主要了解了如何創(chuàng)建并配置 DAO 對象,以及 DBTreaty 數(shù)據(jù)庫規(guī)約是怎樣的一個概念以及初步的使用方法。在后面的章節(jié)中,我們繼續(xù)介紹 DAO 更多的使用方法。
相關(guān)項目
https://gitee.com/LeeFJ/foxnic