1.
在Hibernate持久層之上,可使用DAO組件在此封裝數據庫操作,這也是Java EE應用裏常用的DAO模式。當使用DAO模式時,既體現了業務邏輯組件封裝DAO組件的門面模式,也可分離業務邏輯組件和DAO組件的功能:業務邏輯組件負責業務邏輯的變化,而DAO組件負責持久化技術的變化,這正是橋接模式的引用。
2.
引入DAO模式後,每個DAO組件包含了數據庫的訪問邏輯;每個DAO組件可對一個數據庫表完成基本的CRUD操作。
3.
DAO模式的實現至少需要如下三個部分。
一、DAO工廠類
二、DAO接口
三、DAO接口的實現類
4.
DAO模式是一種更符合軟件工程的開發方式,使用DAO模式有如下理由:
一、DAO模式抽象出數據訪問方式,業務邏輯組件無須理會底層的數據庫訪問細節,而只專注於業務邏輯的實現,業務邏輯組件只負責業務功能的改變。
二、DAO將數據訪問集中在獨立的一層,所有的數據訪問都由DAO對象完成,這層獨立的DAO分離了數據訪問的實現與其他業務邏輯,使得系統更具可維護性。
三、DAO還有助於提升系統的可移植性。獨立的DAO層使得系統能在不同的數據庫之間輕易切換,底層的數據庫實現對於業務邏輯是透明的。數據庫移植時僅僅影響DAO層,不同數據庫的切換不會影響業務邏輯組件,因此提高了系統的可複用性。
四、對於不同的持久層技術,Spring的DAO提供了一個DAO模板,將通用的操作放在模板裏完成,而對於特定的操作,則通過回調接口完成。
5.
幾個通用的方法:
get(Serializable id);根據主鍵加載持久化實例
save(Object entity)保存持久化實例
update(Object entity);更新持久化實例
delete(Object entity);刪除持久化實例
delete(Serializable id);根據主鍵刪除持久化實例
findAll();獲取數據表中全部的持久化實例
6.DAO定義接口
BaseDao.java接口定義如下。
package org.coolerwu.common.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDao<T>{
/**
* 根據ID加載實體
*/
T get(Class<T> entityClazz, Serializable id);
/**
* 保存實體
*/
Serializable save(T entity);
/**
* 更新實體
*/
void update(T entity);
/**
* 刪除實體
*/
void delete(T entity);
/**
* 根據ID刪除實體
*/
void delete(Class<T> entityClazz, Serializable id);
/**
* 獲取所有實體
*/
List<T> findAll(Class<T> entityClazz);
/**
* 獲取實體總數
*/
long findCount(Class<T> entityClazz);
/**
* 根據HQL語句查詢實體
*/
List<T> query(String hql);
/**
* 根據帶佔位符參數HQL語句查詢實體
*/
List<T> query(String hql, Object ... args);
}
EmployeeDao.java接口定義如下。
package org.coolerwu.mydo.dao;
import java.util.List;
import org.coolerwu.common.dao.BaseDao;
import org.coolerwu.mydo.domain.Employee;
public interface EmployeeDao extends BaseDao<Employee>{
/**
*
* @param user 賬號
* @param password 密碼
* @return 查詢到返回true,否則false
*/
List<Employee> queryEmployee(String user, String password);
}
ManagerDao.java接口定義如下。
package org.coolerwu.mydo.dao;
import org.coolerwu.common.dao.BaseDao;
import org.coolerwu.mydo.domain.Manager;
public interface ManagerDao extends BaseDao<Manager>{
}
7.實現DAO組件
BaseDaoImpl.java實現類的源代碼。
package org.coolerwu.common.dao.impl;
import java.io.Serializable;
import java.util.List;
import org.coolerwu.common.dao.BaseDao;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
public class BaseDaoImpl<T> implements BaseDao<T>{
/**
* DAO組件進行持久化操作底層依賴的SessionFactory組件
*/
private SessionFactory sessionFactory;
/**
* 依賴注入SessionFactory所需的setter方法
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
*
* @return
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@SuppressWarnings("unchecked")
@Override
public T get(Class<T> entityClazz, Serializable id) {
return (T) getSessionFactory().getCurrentSession().get(entityClazz, id);
}
@Override
public Serializable save(T entity) {
return getSessionFactory().getCurrentSession().save(entity);
}
@Override
public void update(T entity) {
getSessionFactory().getCurrentSession().saveOrUpdate(entity);
}
@Override
public void delete(T entity) {
getSessionFactory().getCurrentSession().delete(entity);
}
@Override
public void delete(Class<T> entityClazz, Serializable id) {
getSessionFactory().getCurrentSession()
.createQuery("select en from " + entityClazz.getSimpleName()
+ " en where en.id = ?0")
.setParameter("0", id)
.executeUpdate();
}
@Override
public List<T> findAll(Class<T> entityClazz) {
return query("select en from " + entityClazz.getSimpleName()
+ " en");
}
@Override
public long findCount(Class<T> entityClazz) {
List<?> l = query("select count(*) from " + entityClazz.getSimpleName());
if(l != null && l.size() == 1)
return (long)l.get(0);
return 0;
}
@SuppressWarnings("unchecked")
@Override
public List<T> query(String hql) {
return (List<T>)getSessionFactory().getCurrentSession()
.createQuery(hql)
.list();
}
@SuppressWarnings("unchecked")
@Override
public List<T> query(String hql, Object... args) {
Query query = getSessionFactory().getCurrentSession()
.createQuery(hql);
for(int i = 0; i < args.length; i++){
query.setParameter(i + "", args[i]);
}
return (List<T>)query.list();
}
}
EmployeeDaoImpl.java實現類的源代碼。
package org.coolerwu.mydo.dao.impl;
import java.util.List;
import org.coolerwu.common.dao.impl.BaseDaoImpl;
import org.coolerwu.mydo.dao.EmployeeDao;
import org.coolerwu.mydo.domain.Employee;
public class EmployeeDaoImpl extends BaseDaoImpl<Employee> implements EmployeeDao{
@Override
public List<Employee> queryEmployee(String user, String password) {
List<Employee> l = query("select a from Employee as a where a.user = ?0 "
+ "and a.password = ?1", user, password);
return l;
}
}
ManagerDaoImpl.java實現類的源代碼。
package org.coolerwu.mydo.dao.impl;
import org.coolerwu.common.dao.impl.BaseDaoImpl;
import org.coolerwu.mydo.dao.ManagerDao;
import org.coolerwu.mydo.domain.Manager;
public class ManagerDaoImpl extends BaseDaoImpl<Manager> implements ManagerDao{
}
8.部署DAO層
1.DAO組件運行的基礎
應用的DAO組件以Hibernate和Spring爲基礎,由Spring容器負責生成並管理DAO組件。Spring容器複製爲DAO組件注入所需要的基礎SessionFactory。
daoContext.xml的源代碼。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 定義數據源Bean,使用C3P0數據源實現 -->
<!-- 並設置連接數據庫的驅動、URL、用戶名、密碼,
連接池最大連接數、最小連接數、初始連接數等參數 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost:3306/test?useSSL=false"
p:user="root"
p:password="wulang"
p:maxPoolSize="200"
p:minPoolSize="2"
p:initialPoolSize="2"
p:maxIdleTime="20" />
<!-- 定義Hibernate的SessionFactory,並依賴注入數據源,注入上面定義的dataSource -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" >
<!-- annotatedClasses屬性用於列出全部持久化類 -->
<property name="annotatedClasses">
<list>
<value>org.coolerwu.mydo.domain.Employee</value>
<value>org.coolerwu.mydo.domain.Manager</value>
</list>
</property>
<!-- 定義Hibernate的SessionFactory的屬性 -->
<property name="hibernateProperties">
<!-- 指定數據庫方言、是否自動建表、是否生成SQL語句等 -->
<value>
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=true
#開啓二級緩存
hibernate.cache.use_second_level_cache=true
#設置二級緩存的提供者
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
</value>
</property>
</bean>
<!-- 配置DAO組件的模板 -->
<bean id="daoTemplate" abstract="true" lazy-init="true"
p:sessionFactory-ref="sessionFactory"/>
<bean id="employeeDao" class="org.coolerwu.mydo.dao.impl.EmployeeDaoImpl"
parent="daoTemplate"/>
<bean id="managerDao" class="org.coolerwu.mydo.dao.impl.ManagerDaoImpl"
parent="daoTemplate"/>
</beans>
配置文件先配置了一個DAO組件的模板,配置文件爲改模板注入量SessionFactory,而其他DAO組件都繼承了該DAO模板,因此,其他實際的DAO組件也會被注入SessionFactory對象。系統的各具體DAO組件實現類中並未提供setSessionFactory()方法,該方法由其父類BaseDaoImpl提供,用於依賴注入SessionFactory對象。