关于HibnernateDaoSupporrt(转载。备忘,不是很重要)
2013-08-04 10:38
246 查看
3。HibernateDaoSupport 基类:
一个回调实现能够有效地在任何Hibernate数据访问中使用。HibernateTemplate 会确保当前Hibernate的 Session 实例的正确打开和关闭,并直接参与到事务管理中去。 Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如find、load、saveOrUpdate或者delete操作的调用,HibernateTemplate 提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的
HibernateDaoSupport 基类,这个类提供了 setSessionFactory(..) 方法来接受一个 SessionFactory 对象,同时提供了 getSessionFactory() 和 getHibernateTemplate() 方法给子类使用。实例如下:
Java代码
public class ProductDaoImpl
extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category)
throws DataAccessException {
return this.getHibernateTemplate().find(
"from test.Product product where product.category=?", category);
}
}
4。HibernateDaoSupport 基类使用技巧:
HibernateDaoSupport这也是使用HibernateTemplate的方法之一,只是需要dao继承这个类:
Java代码
public class LogDaoImpl
extends HibernateDaoSupport implements LogDao {
@Override
public void save(Log log) {
this.getHibernateTemplate().save(log);
//this.save(log);
System.out.println("log save...");
}
}
dao继承了HibernateDaoSupport类,而这个又拥有sessionFactory和hibernateTemplate的setXXX方法,只要我在初始化这个dao时,注入两个其中一个就可以了。但是这两个setXX方法都为final的,因为不可以重写,这样就不能使用annotation的方式了,只能使用xml的方法了。HibernateDaoSupport部分源代码如下:
Java代码
public abstract
class HibernateDaoSupport extends DaoSupport{
private HibernateTemplate hibernateTemplate;
public final
void setSessionFactory(SessionFactory sessionFactory) {
//......
}
}
public final
void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public final HibernateTemplate getHibernateTemplate() {
return this.hibernateTemplate;
}
//.......其他方法
}
xml注入方法如下:
Java代码
<bean id="logDaoImpl" class="example.dao.impl.LogDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
但是问题又来了,如果dao有多个(甚至几个以上),这样就会有大量的xml配置文件,每个dao需要一个配置一个bean,并且在这个bean中需要注入一个sessionFactory或是hibernateTemplate,这样的工作量是非常的大,并且容易出错。
针对有大量的dao我们提供一个解决方案:
我们可以创建一个类,并且这个类来继承hibernateDaoSupport这个类,由于hibernateDaoSupport类的sessionFactory和hibernateTemplate的setXXX方法是final的,因此不能重写,但我们可以在这个类中注入一个sessionFactory或hibernateTemplate但是setXXX方法名,用其它的。然后让dao来继承这个类,这就dao就可以使用annotation方式注解了。代码如下:
Java代码
@Component
public class SuperDao
extends HibernateDaoSupport {
@Resource(name="hibernateTemplate")
public void setSuperHibernateTemplate(HibernateTemplate hibernateTemplate ){
//在这里为父类HibernateDaoSuppport注入hibernateTemplate或是sessionFactory
super.setHibernateTemplate(hibernateTemplate);
}
}
其它的dao继承这个就可以了,如下所示:
Java代码
@Component
public class LogDaoImpl
extends SuperDao implements LogDao {
@Override
public void save(Log log) {
this.getHibernateTemplate().save(log);
//this.save(log);
System.out.println("log save...");
}
}
其他的用法不在这里累述,请参看Spring的参考文档.下面重点说说Spring HibernateTemplate模板方法与Callback机制.
二。HibernateTemplate源码分析
下面以save()方法为例进行说明,先看源代码:
HibernateCallback接口的代码如下,
它只有一个方法doInHibernate方法:
Java代码
public interface HibernateCallback {
Object doInHibernate(Session session) throws HibernateException, SQLException;
}
HibernateTemplate中的具体操作的方法,如save(),update()的具体实现都采用匿名类的方式实现了该接口,在doInHibernate中完成具体的操作。以save()方法为例:
Java代码
public Serializable save(final Object entity)
throws DataAccessException {
return (Serializable) executeWithNativeSession(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException {
checkWriteOperationAllowed(session);
return session.save(entity);
}
});
}
这段代码重点注意以匿名类的方式实现了
HibernateCallback接口.
然后是executeWithNativeSession()方法如下,在此方法中调用核心方法doExecute,如下所示:
Java代码
public Object executeWithNativeSession(HibernateCallback action) {
return doExecute(action, false,
true);
}
在这个方法中使用本地已存在的Session去执行此次save操作,doExecute代码如下所示:
Java代码
/**
* Execute the action specified by the given action object within a Session.
* @param action callback object that specifies the Hibernate action
* @param enforceNewSession whether to enforce a new Session for this template
* even if there is a pre-bound transactional Session
* @param enforceNativeSession whether to enforce exposure of the native
* Hibernate Session to callback code
* @return a result object returned by the action, or <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
protected Object doExecute(HibernateCallback action,
boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Session session = (enforceNewSession ?
SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));
if (existingTransaction) {
logger.debug("Found thread-bound Session for HibernateTemplate");
}
FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
Session sessionToExpose =
(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
Object result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
doExecute这个方法有点过于复杂,不容易理解,现在我用差不多是伪代码的形式来把doExecute这个方法的大概意思写出为,以便大家理解:
Java代码
public class MyHibernateTemplate {
public Object executeWithNativeSession(HibernateCallback action) {
return doExecute(action, false,
true);
}
protected Object doExecute(HibernateCallback action,
boolean enforceNewSession, boolean enforceNativeSession){
Session session = null;
try {
session = getSession();
session.beginTransaction();
action.doInHibernate(session);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
}finally{
//....进行额外处理
}
return null;
}
private Session getSession() {
// TODO Auto-generated method stub
return new Session();
}
}
如果你觉得使用匿名内部类传参的方式不好理解,你可以先写一个特定针对save操作的实现类来帮助理解它,如下所示:
Java代码
public class HibernateSaveCallbackImpl
implements HibernateCallback {
private Object object ;
public HibernateSaveCallbackImpl(){}
public HibernateSaveCallbackImpl(Object object){
this.object = object;
}
public Object doInHibernate(Session session)
throws HibernateException,
SQLException {
session.save(object);
return null;
}
}
然后再实例化一个HibernateSaveCallbackImpl对象传给MyHibernateTemplate进行使用,如下所示:
Java代码
public static
void main(String[] args) {
HibernateCallback callback = new HibernateSaveCallbackImpl();
HibernateCallback callback2 = new HibernateSaveCallbackImpl("save this object");
new MyHibernateTemplate().executeWithNativeSession(callback);
}
当MyHibernateTemplate中的doExecute方法执行时,执行到
Java代码
action.doInHibernate(session);
时,它会先去执行你传入的引用(也就是你自己)的方法。所以称为回调,这与模板模式中的钩子函数基本是一样的。其实回调,简单的可以说是:将自己的引用传给别的方法,在别的方法里面,通过自己的引用调用自己的方法。
一个回调实现能够有效地在任何Hibernate数据访问中使用。HibernateTemplate 会确保当前Hibernate的 Session 实例的正确打开和关闭,并直接参与到事务管理中去。 Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如find、load、saveOrUpdate或者delete操作的调用,HibernateTemplate 提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的
HibernateDaoSupport 基类,这个类提供了 setSessionFactory(..) 方法来接受一个 SessionFactory 对象,同时提供了 getSessionFactory() 和 getHibernateTemplate() 方法给子类使用。实例如下:
Java代码
public class ProductDaoImpl
extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category)
throws DataAccessException {
return this.getHibernateTemplate().find(
"from test.Product product where product.category=?", category);
}
}
public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao { public Collection loadProductsByCategory(String category) throws DataAccessException { return this.getHibernateTemplate().find( "from test.Product product where product.category=?", category); } }
4。HibernateDaoSupport 基类使用技巧:
HibernateDaoSupport这也是使用HibernateTemplate的方法之一,只是需要dao继承这个类:
Java代码
public class LogDaoImpl
extends HibernateDaoSupport implements LogDao {
@Override
public void save(Log log) {
this.getHibernateTemplate().save(log);
//this.save(log);
System.out.println("log save...");
}
}
public class LogDaoImpl extends HibernateDaoSupport implements LogDao { @Override public void save(Log log) { this.getHibernateTemplate().save(log); //this.save(log); System.out.println("log save..."); } }
dao继承了HibernateDaoSupport类,而这个又拥有sessionFactory和hibernateTemplate的setXXX方法,只要我在初始化这个dao时,注入两个其中一个就可以了。但是这两个setXX方法都为final的,因为不可以重写,这样就不能使用annotation的方式了,只能使用xml的方法了。HibernateDaoSupport部分源代码如下:
Java代码
public abstract
class HibernateDaoSupport extends DaoSupport{
private HibernateTemplate hibernateTemplate;
public final
void setSessionFactory(SessionFactory sessionFactory) {
//......
}
}
public final
void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public final HibernateTemplate getHibernateTemplate() {
return this.hibernateTemplate;
}
//.......其他方法
}
public abstract class HibernateDaoSupport extends DaoSupport{ private HibernateTemplate hibernateTemplate; public final void setSessionFactory(SessionFactory sessionFactory) { //...... } } public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } public final HibernateTemplate getHibernateTemplate() { return this.hibernateTemplate; } //.......其他方法 }
xml注入方法如下:
Java代码
<bean id="logDaoImpl" class="example.dao.impl.LogDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
<bean id="logDaoImpl" class="example.dao.impl.LogDaoImpl"> <property name="hibernateTemplate" ref="hibernateTemplate"></property> </bean>
但是问题又来了,如果dao有多个(甚至几个以上),这样就会有大量的xml配置文件,每个dao需要一个配置一个bean,并且在这个bean中需要注入一个sessionFactory或是hibernateTemplate,这样的工作量是非常的大,并且容易出错。
针对有大量的dao我们提供一个解决方案:
我们可以创建一个类,并且这个类来继承hibernateDaoSupport这个类,由于hibernateDaoSupport类的sessionFactory和hibernateTemplate的setXXX方法是final的,因此不能重写,但我们可以在这个类中注入一个sessionFactory或hibernateTemplate但是setXXX方法名,用其它的。然后让dao来继承这个类,这就dao就可以使用annotation方式注解了。代码如下:
Java代码
@Component
public class SuperDao
extends HibernateDaoSupport {
@Resource(name="hibernateTemplate")
public void setSuperHibernateTemplate(HibernateTemplate hibernateTemplate ){
//在这里为父类HibernateDaoSuppport注入hibernateTemplate或是sessionFactory
super.setHibernateTemplate(hibernateTemplate);
}
}
@Component public class SuperDao extends HibernateDaoSupport { @Resource(name="hibernateTemplate") public void setSuperHibernateTemplate(HibernateTemplate hibernateTemplate ){ //在这里为父类HibernateDaoSuppport注入hibernateTemplate或是sessionFactory super.setHibernateTemplate(hibernateTemplate); } }
其它的dao继承这个就可以了,如下所示:
Java代码
@Component
public class LogDaoImpl
extends SuperDao implements LogDao {
@Override
public void save(Log log) {
this.getHibernateTemplate().save(log);
//this.save(log);
System.out.println("log save...");
}
}
@Component public class LogDaoImpl extends SuperDao implements LogDao { @Override public void save(Log log) { this.getHibernateTemplate().save(log); //this.save(log); System.out.println("log save..."); } }
其他的用法不在这里累述,请参看Spring的参考文档.下面重点说说Spring HibernateTemplate模板方法与Callback机制.
二。HibernateTemplate源码分析
下面以save()方法为例进行说明,先看源代码:
HibernateCallback接口的代码如下,
它只有一个方法doInHibernate方法:
Java代码
public interface HibernateCallback {
Object doInHibernate(Session session) throws HibernateException, SQLException;
}
public interface HibernateCallback { Object doInHibernate(Session session) throws HibernateException, SQLException; }
HibernateTemplate中的具体操作的方法,如save(),update()的具体实现都采用匿名类的方式实现了该接口,在doInHibernate中完成具体的操作。以save()方法为例:
Java代码
public Serializable save(final Object entity)
throws DataAccessException {
return (Serializable) executeWithNativeSession(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException {
checkWriteOperationAllowed(session);
return session.save(entity);
}
});
}
public Serializable save(final Object entity) throws DataAccessException { return (Serializable) executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); return session.save(entity); } }); }
这段代码重点注意以匿名类的方式实现了
HibernateCallback接口.
然后是executeWithNativeSession()方法如下,在此方法中调用核心方法doExecute,如下所示:
Java代码
public Object executeWithNativeSession(HibernateCallback action) {
return doExecute(action, false,
true);
}
public Object executeWithNativeSession(HibernateCallback action) { return doExecute(action, false, true); }
在这个方法中使用本地已存在的Session去执行此次save操作,doExecute代码如下所示:
Java代码
/**
* Execute the action specified by the given action object within a Session.
* @param action callback object that specifies the Hibernate action
* @param enforceNewSession whether to enforce a new Session for this template
* even if there is a pre-bound transactional Session
* @param enforceNativeSession whether to enforce exposure of the native
* Hibernate Session to callback code
* @return a result object returned by the action, or <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
protected Object doExecute(HibernateCallback action,
boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Session session = (enforceNewSession ?
SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));
if (existingTransaction) {
logger.debug("Found thread-bound Session for HibernateTemplate");
}
FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
Session sessionToExpose =
(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
Object result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
/** * Execute the action specified by the given action object within a Session. * @param action callback object that specifies the Hibernate action * @param enforceNewSession whether to enforce a new Session for this template * even if there is a pre-bound transactional Session * @param enforceNativeSession whether to enforce exposure of the native * Hibernate Session to callback code * @return a result object returned by the action, or <code>null</code> * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Session session = (enforceNewSession ? SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession()); boolean existingTransaction = (!enforceNewSession && (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory()))); if (existingTransaction) { logger.debug("Found thread-bound Session for HibernateTemplate"); } FlushMode previousFlushMode = null; try { previousFlushMode = applyFlushMode(session, existingTransaction); enableFilters(session); Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); Object result = action.doInHibernate(sessionToExpose); flushIfNecessary(session, existingTransaction); return result; } catch (HibernateException ex) { throw convertHibernateAccessException(ex); } catch (SQLException ex) { throw convertJdbcAccessException(ex); } catch (RuntimeException ex) { // Callback code threw application exception... throw ex; } finally { if (existingTransaction) { logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate"); disableFilters(session); if (previousFlushMode != null) { session.setFlushMode(previousFlushMode); } } else { // Never use deferred close for an explicitly new Session. if (isAlwaysUseNewSession()) { SessionFactoryUtils.closeSession(session); } else { SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory()); } } } }
doExecute这个方法有点过于复杂,不容易理解,现在我用差不多是伪代码的形式来把doExecute这个方法的大概意思写出为,以便大家理解:
Java代码
public class MyHibernateTemplate {
public Object executeWithNativeSession(HibernateCallback action) {
return doExecute(action, false,
true);
}
protected Object doExecute(HibernateCallback action,
boolean enforceNewSession, boolean enforceNativeSession){
Session session = null;
try {
session = getSession();
session.beginTransaction();
action.doInHibernate(session);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
}finally{
//....进行额外处理
}
return null;
}
private Session getSession() {
// TODO Auto-generated method stub
return new Session();
}
}
public class MyHibernateTemplate {
public Object executeWithNativeSession(HibernateCallback action) { return doExecute(action, false, true); }
protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession){
Session session = null;
try {
session = getSession();
session.beginTransaction();
action.doInHibernate(session);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
}finally{
//....进行额外处理
}
return null;
}
private Session getSession() {
// TODO Auto-generated method stub
return new Session();
}
}
如果你觉得使用匿名内部类传参的方式不好理解,你可以先写一个特定针对save操作的实现类来帮助理解它,如下所示:
Java代码
public class HibernateSaveCallbackImpl
implements HibernateCallback {
private Object object ;
public HibernateSaveCallbackImpl(){}
public HibernateSaveCallbackImpl(Object object){
this.object = object;
}
public Object doInHibernate(Session session)
throws HibernateException,
SQLException {
session.save(object);
return null;
}
}
public class HibernateSaveCallbackImpl implements HibernateCallback { private Object object ; public HibernateSaveCallbackImpl(){} public HibernateSaveCallbackImpl(Object object){ this.object = object; } public Object doInHibernate(Session session) throws HibernateException, SQLException { session.save(object); return null; } }
然后再实例化一个HibernateSaveCallbackImpl对象传给MyHibernateTemplate进行使用,如下所示:
Java代码
public static
void main(String[] args) {
HibernateCallback callback = new HibernateSaveCallbackImpl();
HibernateCallback callback2 = new HibernateSaveCallbackImpl("save this object");
new MyHibernateTemplate().executeWithNativeSession(callback);
}
public static void main(String[] args) { HibernateCallback callback = new HibernateSaveCallbackImpl(); HibernateCallback callback2 = new HibernateSaveCallbackImpl("save this object"); new MyHibernateTemplate().executeWithNativeSession(callback); }
当MyHibernateTemplate中的doExecute方法执行时,执行到
Java代码
action.doInHibernate(session);
action.doInHibernate(session);
时,它会先去执行你传入的引用(也就是你自己)的方法。所以称为回调,这与模板模式中的钩子函数基本是一样的。其实回调,简单的可以说是:将自己的引用传给别的方法,在别的方法里面,通过自己的引用调用自己的方法。
相关文章推荐
- [备忘][转载]关于windows7 IIS 7.5和Vista IIS 7.0 局域网无法访问的解决方法
- 转载_关于“cmath(19): error C2039: “acosf”: 不是“`global namespace'”的成员”的问题
- 关于dao得一些使用问题,以备忘....也用来纪念自己解决得第一个内存泄漏问题
- 【转载】关于DAO和ORM
- 关于VO、PO的理解-java的(PO,VO,TO,BO,DAO,POJO)解释(转载)
- 关于service层和dao层的设计。(转载)
- 关于vc 链接时提示转换coff文件失败的【备忘-转载-来自百度知道】
- [转载]线程间操作无效: 从不是创建控件“ListBox1”的线程访问它
- 【转载】关于sqlserver自增长列的问题
- 关于ARM处理器Remap的理解(转载)
- 关于codeforces比赛规则介绍(转载)
- amo上转载关于dsp烧写和外扩RAM
- 【转载】关于C++中cin的几点说明性总结
- 一次关于创易样品本发展的群聊(转载)
- 关于perl中和C中的sort机制 (转载)
- 关于 greenDao 在studio 里的运行时java.lang.NoClassDefFoundError: org.greenrobot.greendao.query.QueryBuilder
- Perl编程备忘 (转载)
- 转载:关于轮子,总结:只有自己动手才能学到东西,多尝试
- Response.ContentType 详细列表备忘使用(转载)
- (转载)C# Attribute 用法备忘