MiniDao文檔

MiniDao使用指南
作者: 張代浩
2013/08/16
P-2
目錄
 培訓對象
使用MiniDao進行開發的開發人員
 培訓目的
使開發人員掌握通過MiniDao訪問Mysql數據
庫的用法和技巧
 
P-3
目錄
 培訓內容
 MiniDao簡介及特徵
 MiniDao的安裝及基本概念
 MiniDao的使用介紹
 參考資料
 Spring(IOC/AOP/JDBC)
 Freemarker
 Hibernate
P-4
MiniDao簡介及特徵
 MiniDao是Jeecg自己的持久化解決方案,集成Hibernate
 實體維護和Mybaits SQL分離的兩大優點。具有以下特徵
 O/R mapping不用設置xml,零配置便於維護
 不需要了解JDBC的知識
 SQL語句和java代碼的分離
 可以自動生成SQL語句
 接口和實現分離,不用寫持久層代碼,用戶只需寫接口,以及某些接口方法
 對應的SQL。它會通過AOP自動生成實現類
 支持自動事務處理和手動事務處理
 支持與hibernate輕量級無縫集成
 MiniDao整合了Hibernate+mybatis的兩大優勢,支持實體維護和SQL分離
 SQL支持腳本語言
 Sql 性能優於Mybatis
※向下兼容Hibernate實體維護方式,實體的增刪改查SQL自動生成
P-5
&Vs Mybatis
相同點:
 SQL語句和java代碼的分離
不同點:
 O/R mapping不用設置xml,零配置,簡單易用
 可以自動生成SQL語句
 接口和實現分離,不用寫持久層代碼,用戶只需寫接口,以及某些接
口方法對應的SQL。它會通過AOP自動生成實現類
 支持與hibernate輕量級無縫集成
 SQL支持更強大的腳本語言,可以寫邏輯處理
 Sql 性能優於Mybatis
 Sql支持傳遞多個參數Map/Object/List/包裝類型都可以
 Mybatis只支持一個參數<Map/Object>
SQL性能對比
(MiniDao SQL內容採用文件存儲)
MiniDao Sql 耗時: 54 毫秒(SQL模板第一從文件讀取,第二次從緩存讀取)方法第一次執行的時候加載sql到緩存裏
MiniDao Sql 耗時: 4 毫秒
MiniDao Sql 耗時: 4 毫秒
MiniDao Sql 耗時: 5 毫秒
(MiniDao SQL內容採用@Sql標籤)
MiniDao Sql 耗時: 6 毫秒
MiniDao Sql 耗時: 1 毫秒
MiniDao Sql 耗時: 1 毫秒
MiniDao Sql 耗時: 2 毫秒
(Mybatis 在Sesion 初始化的 時候,加載Xml到緩存裏,所以第一執行比MiniDao快)
Mybatis Sql 耗時: 18 毫秒 Mybatis Session初始化的時候,加載Xml到緩存裏
Mybatis Sql 耗時: 6 毫秒
Mybatis Sql 耗時: 5 毫秒
Mybatis Sql 耗時: 9 毫秒
(Spring jdbc)
Springjdbc Sql 耗時: 10 毫秒
Springjdbc Sql 耗時: 1 毫秒
Springjdbc Sql 耗時: 1 毫秒
Springjdbc Sql 耗時: 1 毫秒
P-7
MiniDao支持SQL分離寫法
 第一步: EmployeeDao.java 接口定義(不需要實現)
@MiniDao
public interface EmployeeDao {
 @Arguments("employee")
 public List<Map> getAllEmployees(Employee employee);
 @Arguments("empno")
 Employee getEmployee(String empno);
 
 @Arguments({"empno","name"})
 Map getMap(String empno,String name);
 @Sql("SELECT count(*) FROM employee")
 Integer getCount();
 @Arguments("employee")
 int update(Employee employee);
 @Arguments("employee")
 void insert(Employee employee);
}
P-8
MiniDao支持SQL分離寫法
 第二步:接口方法對應SQL文件創建
 
Sql文件定位到dao接口的方法,dao接口的每個方法對應一個sql文件
SQL文件命名規則:{Dao接口名} _{方法名}.sql
 
簡單SQL,也可以採用方法註釋標籤
@Sql("SELECT count(*) FROM employee")
 Integer getCount();
P-9
MiniDao支持SQL分離寫法
 第三步:SQL文件
SQL文件採用模板語言Freemarker語法,可以靈活運用,甚至可
以寫腳本語言,宏處理等;
示例:
SELECT * FROM employee where 1=1 
<#if employee.age ?exists>
and age = '${employee.age}'
</#if>
<#if employee.name ?exists>
and name = '${employee.name}'
</#if>
<#if employee.empno ?exists>
and empno = '${employee.empno}'
</#if>
P-10
MiniDao支持實體方式維護
 第一步:自定義接口繼承MiniDaoSupportHiber接

 示例:
 public interface JeecgDemoDao extends 
MiniDaoSupportHiber<JeecgDemo>{
說明:JeecgDemo:持久化對象
 JeecgDemoDao 用戶自定義接口
P-11
SQL參數傳遞兩種方式
方式一: 支持採用佔位符,格式字段前加冒號【: 字段名】
 優點: 
 防止sql注入;sql執行計劃只解析一次;字段值根據類型自動轉換
 不需要手工處理
 缺點:只能傳參數原生態值;參數爲List情況循環體不適用
 示例:
• SELECT * FROM employee where 1=1 
• <#if employee.age ?exists>
• and age = :employee.age
• </#if>
• <#if employee.name ?exists>
• and name = :employee.name
• </#if>
• <#if employee.empno ?exists>
• and empno = :employee.empno
• </#if>
P-12
SQL參數傳遞兩種方式
方式二:模板語言方式,格式【${字段名}】
 缺點:
 Sql直接拼裝,有SQL注入風險;參數值需根據類型手工轉換;
 優點:
 可以對參數值進行腳本處理;參數爲List對象,循環體對象必須用該方式;
 (用戶體驗沒有變化,直接將${}改爲: 即可)
 特點:支持多參數,支持參數多層,參數爲list必須採用模板語言方式
 示例:
SELECT * FROM employee where 1=1 
<#if employee.age ?exists>
and age = '${employee.age}'
</#if>
<#if employee.name ?exists>
and name = '${employee.name}'
</#if>
<#if employee.empno ?exists>
and empno = '${employee.empno}'
</#if>
P-13
MiniDao支持SQL分離寫法
 第四步:@Arguments 註釋標籤講解
 /** 
 *(SQL模板參數名)
 * 1. [註釋標籤參數]必須和[方法參數],保持順序一致
 * 2. [註釋標籤參數]的參數數目不能大於[方法參數]的參數數目
 * 3. 只有在[註釋標籤參數]標註的參數,纔會傳遞到SQL模板裏
 * 4. 如果[方法參數]只有一個,如果用戶不設置 [註釋標籤參數],則默認參數名爲miniDto
 * @date 20130817
 * @version V1.0
 */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
 public @interface Arguments {
 String[] value() default {};
 }
• 示例:
 @Arguments({"empno","name"})
 Map getMap(String empno,String name);
P-14
MiniDao支持實體方式維護
 第二步:JavaBean實體定義,採用JPA方式進行註解
 ※ 同Hibernate實體配置一樣,支持一對多,多對多等複雜配置關係
 示例:
@Entity
 @Table(name = "jeecg_demo")
 @Inheritance(strategy = InheritanceType.JOINED)
 public class JeecgDemo extends IdEntity implements java.io.Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid")
private String id;
/**手機號碼*/
@Column(name ="mobilePhone",nullable=true)
private java.lang.String mobilePhone;
/**辦公電話*/
@Column(name ="officePhone",nullable=true)
private java.lang.String officePhone;
/**電子郵箱*/
@Column(name ="email",nullable=true)
private java.lang.String email;
P-15
MiniDao的安裝及基本概念
 MiniDao的安裝
 與Jeecg同樣,MiniDao需要JDK1.5以上的系統環境
 需要引入必要的lib文件
 引入必要的配置文件
Spring.xml,log4j.properties
 使用MiniDao時必須作成的
文件:JavaBeans、
Dao(.java)、
SQL文件(.sql)
P-16
MiniDao的安裝及基本概念(2)
 MiniDao的基本概念
 使用MiniDao功能時,作成的JavaBeans,
Dao(.java),spring.xml文件,SQL文件(.sql)之
間關係如下圖: 
P-17
MiniDao的安裝及基本概念(2)
 MiniDao配置文件
• <!-- MiniDao動態代理類 -->
• <bean id="miniDaoHandler" 
class="org.jeecgframework.minidao.aop.MiniDaoHandler">
• <property name="jdbcTemplate" ref="jdbcTemplate"></property>
• </bean>
• <!-- 註冊MiniDao接口 -->
• <bean class="org.jeecgframework.minidao.factory.MiniDaoBeanFactory">
• <property name="packagesToScan">
• <list>
• <value>examples.dao.*</value>
• </list>
• </property>
• </bean>
P-18
MiniDao的安裝及基本概念(3)
 MiniDao的基本概念
 JavaBeans,採用JPA註解註解方式:
 JavaBeans用來和表進行關聯。 爲了將
JavaBeans和表進行關聯,必須進行以下的常
量聲明和方法的實裝: 
– 和表關聯的常量聲明 (TABLE註釋) 
– 和列項關聯的常量聲明 (COLUMN註釋) 
– 和其他的表結合時指定爲鍵(key)的常量聲明
(N:1映射) 
– getter/setter方法的實裝
P-19
MiniDao的安裝及基本概念(4)
 MiniDao的基本概念
 Dao(Data Access Object): 
 Dao作爲接口而作成。Dao本來的目的,就是通過把持
久化的數據和處理邏輯相分離,來維持Bean的持久化
。 Dao和JavaBeans的關係是1:1的關係,也即,有一個
JavaBeans,就要作成一個Dao。 通過調用Dao的方法
(method),來執行與方法(method)相對應的SQL文件
中的SQL指令。 在作成Dao的時候,必須注意以下幾
點:
– 與JavaBeans關聯的常量聲明(BEAN註釋) 
– 方法(method)的定義
P-20
MiniDao的安裝及基本概念(5)
 MiniDao的基本概念
 SQL文件: 
 SQL文件裏記述SQL檢索,更新等指令。 一旦
調用Dao裏定義的方法(method),就可以執行
對應的SQL文件中記述的SQL指令。 請將作成
的SQL文件與Dao放在同一個命名空間下。
P-21
MiniDao的安裝及基本概念(6)
 MiniDao的基本概念
 Spring.xml文件: 
 在xml文件進行Dao配置,把Dao作爲組件(component)
註冊到Spring容器(container)中。要使用Dao功能,對
已註冊的Dao,必須進行AOP的應用。Dao實體配置文
件部分內容如下所示:
<!-- 註冊JeecgDemoDao接口 -->
<bean id="jeecgDemoDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="examples.dao.JeecgDemoDao" />
<property name="interceptorNames">
<list>
<value>miniDaoHandler</value>
</list>
</property>
</bean>
P-22
MiniDao的安裝及基本概念(7)
 MiniDao的基本概念
 MiniDao的執行: 
 執行Dao的基本方法如下所示:
1. 以spring.xml文件中配置需要管理的Dao接口,將
Dao註冊進Spring容器中
2. 從Spring容器中調用getBean,取得已註冊的Dao
3. 執行所得到的Dao的方法(method)
P-23
MiniDao的安裝及基本概念(8)
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import examples.dao.JeecgDemoDao;
import examples.entity.JeecgDemo;
public class Client {
public static void main(String args[]) {
BeanFactory factory = new ClassPathXmlApplicationContext(
"applicationContext.xml");
JeecgDemoDao jeecgDemoDao = (JeecgDemoDao) 
factory.getBean("jeecgDemoDao");
JeecgDemo entity = new JeecgDemo();
entity.setId("402880e7408c7c5001408c7c52400000");
entity.setAge(20999);
entity.setUserName("zhangdaihao 12121");
JeecgDemo s = 
jeecgDemoDao.getByHiber("402880e7408c9b1601408c9b179a0000");
System.out.println(s.getUserName());
}
}
 
P-24
MiniDao的使用介紹
 JavaBeans
 和表關聯的常量聲明 (TABLE註釋) 
要和表進行關聯,使用TABLE註釋。 TABLE註釋
使用以下的形式進行常量聲明:
@Table(name = "jeecg_demo")
這也可以用於定義schema。schema名爲
“SCOTT”的場合,聲明如下所示:
@Table(name = "jeecg_demo",schema="scott")
P-25
MiniDao的使用介紹(2)
 JavaBeans
 和列項關聯的常量聲明 (COLUMN註釋) 
要和表的列項進行關聯,使用COLUMN註釋。
@Column(name="USER_NAME",nullable=false)
public java.lang.String getUserName(){
return this.userName;
}
P-26
MiniDao的使用介紹(3)
 JavaBeans
 和其他的表結合時指定爲鍵(key)的常量聲明 (N:1映射)
 @ManyToOne(fetch=FetchType,cascade=CascadeType)
可選
@ManyToOne表示一個多對一的映射,該註解標註的屬性通常是數據庫表的外鍵
optional:是否允許該字段爲null,該屬性應該根據數據庫表的外鍵約束來確定,默認爲
true
fetch:表示抓取策略,默認爲FetchType.EAGER
cascade:表示默認的級聯操作策略,可以指定爲ALL,PERSIST,MERGE,REFRESH
和REMOVE中的若干組合,默認爲無級聯操作
targetEntity:表示該屬性關聯的實體類型.該屬性通常不必指定,ORM框架根據屬性
類型自動判斷targetEntity.
示例:
//訂單Order和用戶User是一個ManyToOne的關係
//在Order類中定義
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
 return user;
}
P-27
MiniDao的使用介紹(4)
 JavaBeans
 對應於列項(column)的實例(instance)變量聲明
列項的值用Bean的實例變量表示。實例變量的聲
明方式有兩種。
• 作爲JavaBeans的屬性的聲明方式
 getter method 
 public 類型 get屬性名()
 setter method
 public void set屬性名(參數)
• 作爲public字段的聲明方式
P-28
MiniDao的使用介紹(5)
 Dao
 方法(method)的定義
雖然通過調用Dao裏定義
的方法(method),可以
執行相應的SQL文件中
記述的SQL指令,但是
在更新處理和檢索處理
中需要遵循各自的方法
命名規約。方法
(method)名必須以右表
中列出的單詞開頭
處理 名稱
插入 insert,add,create
更新 update,modify,store
刪除 delete,remove
批處理 batch
檢索 以上各單詞之外
P-29
MiniDao的使用介紹(6)
 Dao
 INSERT處理
進行INSERT處理的方法名,必須以
insert,add,create開頭。 返回值可以指定爲
void或者int。 int的場合,返回值爲更新的行數
。參數類型與實體(Entity)的類型要一致。
– public void insert(Department department);
– public int addDept(Department department);
– public void createDept(Department 
department);
P-30
MiniDao的使用介紹(7)
 Dao
 UPDATE處理
進行UPDATE處理的方法名,必須以update,modify,store
開頭。 返回值可以指定爲void或者int。int的場合,返
回值爲更新的行數。參數類型與實體(Entity)的類型要
一致。
– public int update(Department department);
– public int modifyDept(Department department);
– public void storeDept(Department department);
P-31
MiniDao的使用介紹(10)
 Dao
 DELETE處理
進行DELETE處理的方法名,必須以
delete,remove開頭。 返回值可以爲void或者int
類型。 int的場合,返回值爲更新的行數。參數
類型與實體(Entity)的類型要一致。
– public void delete(Department department);
– public int removeDept(Department 
department);
P-32
MiniDao的使用介紹(11)
 Dao
 檢索(SELECT)處理
進行檢索處理的場合,要指定返回值的類型。返
回值的類型是java.util.List的實裝的場合,
SELECT指令將返回實體(Entity)的列表(List)。
返回值是實體(Entity)型的數組(array)的場合,
返回實體數組(Entity array)。返回值的類型是
實體(Entity)的場合,將返回實體(Entity)。
– public List selectList(int deptno);
– public Department[] selectArray(int deptno);
P-33
MiniDao的使用介紹(12)
 Dao
 檢索(SELECT)處理
除了實體(Entity)以外,還可以利用DTO或者Map作爲檢索
處理的返回值。 返回值爲DTO類型的列表(List<Dto>)
的場合,將返回DTO的列表(List)。 返回值爲DTO類型
的數組(Dto[])的場合,將返回DTO的數組(array)。 返
回值爲Map類型的列表(List<Map>)的場合,將返回
Map的列表(List)。 返回值爲Map類型的數組(Map[])的
場合,將返回Map的數組(array)。
– public List<EmpDto> selectAsDtoList(int deptno);
– public EmpDto[] selectAsDtoArray(int deptno);
– public List<Map> selectAsMapList(int deptno);
– public Map[] selectAsMapArray(int deptno);
P-34
MiniDao的使用介紹(13)
 Dao
 檢索(SELECT)處理
除此以外的場合,MiniDao還想定了這樣一種情
況,也即,像SELECT count(*) FROM emp這
樣的指令,返回值爲1行只有一個列項值的情
況。
– public int selectCountAll();
P-35
MiniDao的使用介紹(14)
 Dao
 @Arguments註釋標籤
使用@Arguments註釋指定方法(method)的參數名,這樣
就可以在SQL指令中引用方法(method)的參數。
 @Arguments({"empno","name"})
 Map getMap(String empno,String name);
方法(method)的參數與表的列名相對應的場合,在參數
名中指定表的列名。
例如:方法(method)的參數名是empno,表的列名是
employeeno的場合,就指定爲employeeno。
 如果是有複數個參數的場合,則用逗號分隔。
P-36
MiniDao的使用介紹(15)
 SQL文件(支持Freemarker語法)
 IF註解(comment)
使用IF註解,可以根據相應的條件改變要執行的SQL指令。IF註解的
記法如下:
<#if condition>...
<#elseif condition2>...
<#elseif condition3>......
<#else>..
例:
<#if employee.empno ?exists>
and empno = '${employee.empno}'
</#if>
作爲IF註解的條件爲假的處理部分,使用ELSEIF註解。 條件爲假的
場合,使用<#else>..之後的部分
P-37
MiniDao的使用介紹(16)
 MiniDao實體Bean調用方法
BeanFactory factory = new ClassPathXmlApplicationContext(
"applicationContext.xml");
 
EmployeeDao employeeDao = (EmployeeDao) 
factory.getBean("employeeDao");
Employee employee = new Employee();
List<Map> list = employeeDao.getAllEmployees(employee);
for(Map mp:list){
System.out.println(mp.get("id"));
System.out.println(mp.get("name"));
System.out.println(mp.get("empno"));
System.out.println(mp.get("age"));
System.out.println(mp.get("birthday"));
System.out.println(mp.get("salary"));

P-38
MiniDao的使用介紹(17)
 MiniDao測試分離SQL
BeanFactory factory = new ClassPathXmlApplicationContext(
"applicationContext.xml");
 
EmployeeDao employeeDao = (EmployeeDao) 
factory.getBean("employeeDao");
Employee employee = new Employee();
List<Map> list = employeeDao.getAllEmployees(employee);
for(Map mp:list){
System.out.println(mp.get("id"));
System.out.println(mp.get("name"));
System.out.println(mp.get("empno"));
System.out.println(mp.get("age"));
System.out.println(mp.get("birthday"));
System.out.println(mp.get("salary"));

P-39
MiniDao的使用介紹(18)
 MiniDao測試實體Bean維護
public class HiberClient {
public static void main(String args[]) {
BeanFactory factory = new ClassPathXmlApplicationContext(
"applicationContext.xml");
JeecgDemoDao jeecgDemoDao = (JeecgDemoDao) 
factory.getBean("jeecgDemoDao");
JeecgDemo s = 
jeecgDemoDao.getByIdHiber(JeecgDemo.class,"402880e7408f53a40
1408f53a5aa0000");
if(s!=null){
System.out.println(s.getUserName());
}
}

}


參考資料
 技術論壇:http://www.jeecg.org
 作者:張代浩
 聯繫方式:[email protected]
 QQ交流羣:325978980,143858350
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章