spring

spring 封装了hibernate dao的操作:学习中遇到的问题,以及自己的见解

一、使用了由spring框架提供的对hibernate3的封装。这样做无非是为了使用spring提供的对事务的统一管理。当我们用到由spring所封装的hibernate的时候一定会用到一个类:HibernateTemplate.这是一个对持久层处理封装的非常完整的类,包括对session的管理(事实上session的获取于释放是一个令人头疼的问题)等等,我们通常会使用HibernateTemplate的excute方法来进行数据库操作(即使我们调用的也许是别的类似于find、get之类的方法,但是实质上最终还是转变为了调用excute方法)。

 

 

 

 

1.这里采用的方法:HibernateBaseDao (自定义一个类)
/**
*package org.springframework.orm.hibernate3.support.HibernateDaoSupport;

*HibernateDaoSupport是spring中的类
*/
HibernateBaseDao extends HibernateDaoSupport{

这中间是一系列实现的对数据库的crud操作
public void executeBatchUpdate(final List sqls) {
  //new HibernateDaoSupport().
   getHibernateTemplate().execute(new HibernateCallback() {
        public Object doInHibernate(Session session) throws HibernateException {
          try{
            Connection con = session.connection();
            Statement st = con.createStatement();
            for (int i = 0; i < sqls.size(); i++) {
           String sql= (String) sqls.get(i);
              st.addBatch( sql );
log.debug("exec sqls["+i+"]"+sql);              
            }
            if(sqls.size()>0)
                st.executeBatch();
          }catch (SQLException ex) {
           ex.printStackTrace();
            throw new DataAccessResourceFailureException(ex.getMessage());
          }
          return null;
        }
      });
 }
------获取连接-----------
public Connection getJDBCConnection() {
  return (Connection)getHibernateTemplate().execute(new HibernateCallback() {
        public Object doInHibernate(Session session) throws HibernateException {
          return session.connection();
        }
      });
 }

 

}

 

我们系统中的dao实现类daoimpl 中需要用到 用到HibernateBaseDao 中的方法
那么我们只需要将HibernateBaseDao 的对象通过spring注入到daoimpl中即可

public class BaseDAOImp implements IBaseDAO {

    private HibernateBaseDao  hibernateBaseDao;
    public static Log log = LogFactory.getLog(BaseDAOImp.class);

    public void setHibernateBaseDao(HibernateBaseDao hibernateBaseDao) {
 this.hibernateBaseDao = hibernateBaseDao;
    }
   
 public void saveVo(VO obj) {
  //
  hibernateBaseDao.saveObject(obj);
 }

 public void removeVo(VO obj) {
  //
  hibernateBaseDao.removeObject(obj);
 }


-------------------总结-------------
通常这样操作我们需要给类HibernateBaseDao 注入一个SessionFactory的实例,他的作用就是获取jdbc连接
<bean id="hibernateBaseDao" class="com.sitech.crmpd.core.dao.HibernateBaseDao">
  <property name="sessionFactory">
   <ref bean="sessionFactory" />
  </property>
 </bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource">
   <ref bean="chnds" />  //数据源
  </property>
  <property name="mappingDirectoryLocations">
   <list>
       <value>/sitech/res/s99899/hbm</value>    
   </list>
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
    <prop key="hibernate.use_outer_join">false</prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
   </props>
  </property>
 </bean>

 

 

 

这里的疑问:hibernateBaseDao 继承自HibernateDaoSupport()类而这个类其实是没有sessionFactory这个属性的。哪是从哪里来的这个属性呢,又是如何注入的呢

通过看源码发现了注入的方式:
1.HibernateDaoSupport类有
public abstract class HibernateDaoSupport extends DaoSupport {
       private HibernateTemplate hibernateTemplate;//属性


 public final void setSessionFactory(SessionFactory sessionFactory) {
   this.hibernateTemplate = createHibernateTemplate(sessionFactory);  //有了这个方法,那么它的子类HibernateDaoSupport 也就有了这个方法,spring会调用这个方法进行注入(注入方式:是看是否有这个set方法,如:setSessionFactory),
 }
      protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {//在上面的set方法中会调用这个方法
  return new HibernateTemplate(sessionFactory);//这里调用构造方法

 }
      public final SessionFactory getSessionFactory() {
  return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);//方法

 }
)
HibernateTemplate 类:
public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {


public HibernateTemplate(SessionFactory sessionFactory) {
  setSessionFactory(sessionFactory);//这个方法是调用的父类的方法,如下面所示
  afterPropertiesSet();
 }
}

HibernateAccessor 类
public abstract class HibernateAccessor implements InitializingBean, BeanFactoryAware {

protected final Log logger = LogFactory.getLog(getClass());

 private SessionFactory sessionFactory;

 private Object entityInterceptor;

 private SQLExceptionTranslator jdbcExceptionTranslator;

 private int flushMode = FLUSH_AUTO;

 private String[] filterNames;

      public void setSessionFactory(SessionFactory sessionFactory) {
  this.sessionFactory = sessionFactory;
 }
}

----------------------------------------------------

 

 

二、关于回调函数
说明:HibernateCallback是一个接口
public interface HibernateCallback {

Object doInHibernate(Session session) throws HibernateException, SQLException;
}
如:
public Connection getJDBCConnection() {
  return (Connection)getHibernateTemplate().execute(new HibernateCallback() {
        public Object doInHibernate(Session session) throws HibernateException {
          return session.connection();
        }
      });
 }

 


这里使用了回调的方式;
1.HibernateTemplate,内联类

2.内联类实现接口HibernateCallback的doInHibernate 方法

3.HibernateTemplate拥有一个参数为HibernateCallback接口类型的函数execute(HibernateCallback action)方法.

4.调用HibernateTemplate的get方法时,将内联类传给了excute方法

5.执行excute方法时,(你调用它)

已取得内联类,就可以随时回调它所实现的HibernateCallback接口中的方法了,

这时它反过来调用你的方法(它调用你),这就是回调了.

Javaeye两个会员的理解,我觉得比较到位.

概括:(
就是调用系统的一个方法,传进去一个接口的实现类 or 匿名类。

然后系统的方法调用接口申明的方法,并且注入相应的参数 )


这里Excute方法的参数是一种匿名类的方式。为什么要采用匿名类呢(不管怎么说匿名类看起来总是让人觉得不舒服)?这个地方是否必须采用匿名类呢?

1、回调:excute方法会回调HibernateCallback类型的doInHibernate方法;
2、匿名类参数:我们为excute方法提供的参数并不是一个真正创建出来的;
3、动态创建回调方法:

如果不采用匿名类,我们需要做的是为HibernateCallback创建一个实现类,并且实现doInHibernate方法

但是最要命的问题是doInHibernate方法的实现对于我们的实际需求来说每一次调用可能都是不一样的(在doInHibernate方法中我们使用session进行数据库操作,对于不同的业务逻辑,方法实现必定是不一样的),采用了匿名类我们不用在代码重创建新的类型,而且可以动态的创建我们所需要的回调函数。

这里的回调是这样的
首先是 getHibernateTemplate().execute()-->execute中HibernateCallback .doInHibernate();

实现回调的地方

 


public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {
  Assert.notNull(action, "Callback object must not be null");

  Session session = getSession();
  boolean existingTransaction = 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 = (exposeNativeSession ? 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());
    }
   }
  }
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值