在開發采用Struts2+Spring+hibernate這三大框架的項目時,我們需要一個抽取一個BaseDao。這個Dao里面CRUD都給封裝好,
后續的其他Dao直接用它的功能就可以。Spring里面有個HibernateDaoSupport的類,這個類需要給他一個SessionFactory。
有了SessionFactory后,
他就可以做各種操作;最強大的功能是它可以getHibernateTemplate來獲取一個HibernateTemplate。有了HibernateTemplate,就有了各種CRUD方法。廢話不多說,下面直接看代碼
一、BaseDao接口及實現的代碼
(1)BaseDao接口的代碼
package com.tax.core.dao;
import java.io.Serializable;
import java.util.List;
/**
* BaseDao
* @author ZENG.XIAO.YAN
* @date 2017年6月29日 上午10:36:57
* @version v1.0
*/
public interface BaseDao<T> {
/**
* 新增
* @param entity
*/
public void save(T entity);
/**
* 更新
* @param entity
*/
public void update(T entity);
/**
* 根據id刪除
* @param id
*/
public void deleteById(Serializable id);
/**
* 通過id查找
* @param id
* @return 實體
*/
public T findById(Serializable id);
/**
* 查找所有
* @return List集合
*/
public List<T> findAll();
}
45
1
package com.tax.core.dao;
2
import java.io.Serializable;
3
import java.util.List;
4
5
/**
6
* BaseDao
7
* @author ZENG.XIAO.YAN
8
* @date 2017年6月29日 上午10:36:57
9
* @version v1.0
10
*/
11
public interface BaseDao<T> {
12
13
/**
14
* 新增
15
* @param entity
16
*/
17
public void save(T entity);
18
19
/**
20
* 更新
21
* @param entity
22
*/
23
public void update(T entity);
24
25
/**
26
* 根據id刪除
27
* @param id
28
*/
29
public void deleteById(Serializable id);
30
31
32
/**
33
* 通過id查找
34
* @param id
35
* @return 實體
36
*/
37
public T findById(Serializable id);
38
39
40
/**
41
* 查找所有
42
* @return List集合
43
*/
44
public List<T> findAll();
45
}
(2)BaseDaoImpl的代碼
package com.tax.core.dao.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.tax.core.dao.BaseDao;
/**
* BaseDaoImpl
* @author ZENG.XIAO.YAN
* @date 2017年6月29日 下午12:23:16
* @version v1.0
*/
public abstract class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
private Class<T> clazz;
// 按照類型自動注入SessionFactory; 在實例化的時候,Spring按照形參的類型自動注入
@Autowired
public void setMySessionFactory(SessionFactory sessionFactory){
setSessionFactory(sessionFactory);
}
public BaseDaoImpl() {
//this表示當前被實例化的對象;如UserDaoImpl
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();//BaseDaoImpl<User>
clazz = (Class<T>)pt.getActualTypeArguments()[0];
}
/**
* 獲取session
* @return session
*/
public Session getCurrentSession(){
Session session = null;
try {
session = getSessionFactory().getCurrentSession();
} catch (HibernateException e) {
throw new RuntimeException("getCurrentSession error", e);
//session = getSessionFactory().openSession();
}
return session;
}
@Override
public void save(T entity) {
getHibernateTemplate().save(entity);
}
@Override
public void update(T entity) {
getHibernateTemplate().update(entity);
}
@Override
public void deleteById(Serializable id) {
getHibernateTemplate().delete(findById(id));
}
@Override
public T findById(Serializable id) {
return getHibernateTemplate().get(clazz, id);
}
@Override
public List<T> findAll() {
Session session = getCurrentSession();
Query query = session.createQuery("FROM "+ clazz.getSimpleName());
return query.list();
}
}
x
1
package com.tax.core.dao.impl;
2
3
import java.io.Serializable;
4
import java.lang.reflect.ParameterizedType;
5
import java.util.List;
6
import org.hibernate.HibernateException;
7
import org.hibernate.Query;
8
import org.hibernate.Session;
9
import org.hibernate.SessionFactory;
10
import org.springframework.beans.factory.annotation.Autowired;
11
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
12
13
import com.tax.core.dao.BaseDao;
14
15
/**
16
* BaseDaoImpl
17
* @author ZENG.XIAO.YAN
18
* @date 2017年6月29日 下午12:23:16
19
* @version v1.0
20
*/
21
public abstract class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
22
23
private Class<T> clazz;
24
25
// 按照類型自動注入SessionFactory; 在實例化的時候,Spring按照形參的類型自動注入
26
27
public void setMySessionFactory(SessionFactory sessionFactory){
28
setSessionFactory(sessionFactory);
29
}
30
31
32
public BaseDaoImpl() {
33
//this表示當前被實例化的對象;如UserDaoImpl
34
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();//BaseDaoImpl<User>
35
clazz = (Class<T>)pt.getActualTypeArguments()[0];
36
}
37
38
/**
39
* 獲取session
40
* @return session
41
*/
42
public Session getCurrentSession(){
43
Session session = null;
44
try {
45
session = getSessionFactory().getCurrentSession();
46
} catch (HibernateException e) {
47
throw new RuntimeException("getCurrentSession error", e);
48
//session = getSessionFactory().openSession();
49
}
50
return session;
51
}
52
53
54
public void save(T entity) {
55
getHibernateTemplate().save(entity);
56
}
57
58
59
public void update(T entity) {
60
getHibernateTemplate().update(entity);
61
}
62
63
64
public void deleteById(Serializable id) {
65
getHibernateTemplate().delete(findById(id));
66
}
67
68
69
public T findById(Serializable id) {
70
return getHibernateTemplate().get(clazz, id);
71
}
72
73
public List<T> findAll() {
74
Session session = getCurrentSession();
75
Query query = session.createQuery("FROM "+ clazz.getSimpleName());
76
return query.list();
77
}
78
79
}
(3)對BaseDaoImpl的說明
使用HibernateDaoSupport需要注入SessionFactorytory,這個注入的動作其實可以交給BaseDaoImpl的子類去完成的。
如:StudentImpl繼承了BaseDaoImpl。那么在Spring的xml文件按照下面配置即可
但是:我覺得這樣很麻煩,而且我Dao層我想直接用注解。我不想在每個Dao里都去寫這個注入的動作。
所以就准備在BaseDaoImpl里面去完成這個注入動作。
下面開始了我的探索之路:
方案一: 在BaseDaoImpl里面定義SessionFactory的屬性,然后屬性用注解把它注入。
最后在構造器里把這個SessionFactory通過set給HibernateDaoSupport。
具體的如下圖:
結果:雖然想法沒問題,但是后面發現在實例化的時候,這個sessionFactory還沒注進來。
在項目啟動的是時候就報錯了,因為我給別人的SessionFactory個設置為null了;所以失敗了。
后面通過百度發現,原來
Spring容器管理的類中,這個@Autowired注入是在對象實例化完成之后。
所以對Spring容器對bean的實例化過程的還是需要掌握的,筆者在這塊掌握得不好。
方案二:
在BaseDaoImpl中定義一個方法,在方法上加個注解。然后方法中把注解注入的形參(sessionFactory)
通過set給HibernateDaoSupport。
具體如下圖:
結果: 注入成功,這個注解是根據形參的類型自動注入的。sessionFactory會在Spring實例化這Dao后注入。
通過這個探索,發現了自己對Spring的知識掌握得不夠,不知道用注解來注入是在對象實例化之后。
二、使用寫好的BaseDao和BaseImpl
(1)Dao接口直接繼承BaseDao即可,下面以StudentDao接口為例
(2)Dao的實現類,需要繼承BaseDaoImpl,下面以StudentDaoImpl為例
三、結束語
通過抽取這個BaseDao,后續的CRUD就很方便了。
