`

Hibernate_HibernateCallback

 
阅读更多

HibernateTemplate还提供一种更加灵活的方式来操作数据库,通过这种方式可以完全使用Hibernate的操作方式。HibernateTemplate的灵活访问方式是通过如下两个方法完成:

Object execute(HibernateCallback action)

List execute(HibernateCallback action)

这两个方法都需要一个HibernateCallback的实例,HibernateCallback实例可在任何有效的Hibernate数据访问中使用。程序开发者通过HibernateCallback,可以完全使用Hibernate灵活的方式来访问数据库,解决Spring封装Hibernate后灵活性不足的缺陷。HibernateCallback是一个接口,该接口只有一个方法doInHibernate(org.hibernate.Session session),该方法只有一个参数Session。在开发中提供HibernateCallback实现类时,必须实现接口里包含的 doInHibernate方法,在该方法体内即可获得Hibernate Session的引用,一旦获得了Hibernate Session的引用,就可以完全以Hibernate的方式进行数据库访问。

注意:方法doInHibernate方法内可以访问Session,该Session对象是绑定到该线程的Session实例。该方法内的持久层操作,与不使用Spring时的持久层操作完全相同。这保证对于复杂的持久层访问,依然可以使用Hibernate的访问方式。

 

通常,程序中采用实现HibernateCallback的匿名内部类来获取HibernateCallback的实例,方法doInHibernate的方法体就是Spring执行的持久化操作。具体代码如下:

 

public class PersonDaoImpl implements PersonDao

{

 private SessionFactory sessionFactory;

 public void setSessionFactory(SessionFactory sessionFactory){

  this.sessionFactory = sessionFactory;

 }

 /**

  * 

  * 通过人名查找所有匹配该名的Person实例

  * 

  * @param name

  *            匹配的人名

  * 

  * @return 匹配该任命的全部Person集合

  * 

  */

 public List findPersonsByName(final String name){

  HibernateTemplate hibernateTemplate =new HibernateTemplate(this.sessionFactory); // 创建HibernateTemplate实例

  return (List) hibernateTemplate.execute( // 返回HibernateTemplate的execute的结果

    // 创建匿名内部类

    new HibernateCallback(){

     public Object doInHibernate(Session session) throws HibernateException{

      List result = session.createCriteria(Person.class).add(Restrictions.like("name", name+"%").list();

      return result;

     }

    });

    }

}

 

 

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

Spring 对 hibernate 的集成(使用回调callback)

 

比如在删除一条在数据库操作的时候 我们一般是类似是这样使用:

this.getHibernateTemplate().delete("from Information where INFOID='"+infoid.trim()+"'");

 

然而具体在spring内部是怎么操作的呢?

delete()----->excecute()----->执行回调方法HibernateCallback .doInHibernate()。

 

下面来让我们来直接看一下spring的源代码。

//hibernate回调接口

public interface HibernateCallback {

Object doInHibernate(Session session) throws HibernateException, SQLException;

}

//...

 

package org.springframework.orm.hibernate;

public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {

//...

 

public int delete(final String queryString) throws DataAccessException {

  Integer deleteCount = (Integer) execute(new HibernateCallback() {//定义回调实现

   public Object doInHibernate(Session session) throws HibernateException {

    checkWriteOperationAllowed(session);

    return new Integer(session.delete(queryString));//此处有hibernate的实现操作

   }

  });

  return deleteCount.intValue();

 }

 

 public Object execute(HibernateCallback action) throws DataAccessException {

  Session session = (!isAllowCreate() ? SessionFactoryUtils.getSession(getSessionFactory(), false) :

  SessionFactoryUtils.getSession(getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator()));

  boolean existingTransaction = TransactionSynchronizationManager.hasResource(getSessionFactory());

  if (!existingTransaction && getFlushMode() == FLUSH_NEVER) {

   session.setFlushMode(FlushMode.NEVER);

  }

  try {

   Object result = action.doInHibernate(session);//此处调用hibernatecallback回调接口即hibernate的实现

   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 {

   SessionFactoryUtils.closeSessionIfNecessary(session, getSessionFactory());

  }

 }

 

//...

 

//其他操作类似

}

 

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

Hibernate中运用doInHibernate 构造公用findByhql和updateByHql方法

 

在hibernate中,运用doInHibernate,避免了手动open session和close session ,减少了一系列session关闭的麻烦。

 

公用的setParameter 方法,下面有调用,传入一个query 实例,和Map<String, Object> map 类型的参数

private void setParameter(Query query, Map<String, Object> map) {

  if (map != null && !map.isEmpty()) {

   Set<String> keySet = map.keySet();

   for (String string : keySet) {

    Object obj = map.get(string);

    // 这里考虑传入的参数是什么类型,不同类型使用的方法不同

    if (obj instanceof Collection<?>) {

     query.setParameterList(string, (Collection<?>) obj);

    } else if (obj instanceof Object[]) {

     query.setParameterList(string, (Object[]) obj);

    } else {

     query.setParameter(string, obj);

    }

   }

  }

 }

 

 

public void updateByHql(final String hql, final Map<String, Object> map) throws Exception {

  template.execute(new HibernateCallback() {

      @Override

      public Object doInHibernate(Session session) throws HibernateException, SQLException {

         Query query = session.createQuery(hql);

         setParameter(query, map); //调用set参数的方法

         query.executeUpdate();

         return null;

         }

      });

    }

 

public List<Object> findByHql(final String hql, final Map<String, Object> map) throws Exception {

  return (List<Object>) template.execute(new HibernateCallback() {

   public List<Object> doInHibernate(final Session session) throws HibernateException, SQLException {

    Query query = session.createQuery(hql);

    setParameter(query, map);

    return query.list();

   }

  });

}

 

 

调用例子:

String hql = "from ABC where bb = :aa";

  Map<String, Object> map = new HashMap<String, Object>();

  map.put("aa", 22);

  List<Object> cList = commonDao.findByHql(hql, map);

  if (cList == null || cList.size() == 0)

   return null;

  else

   return (ABC) cList.get(0);

 

update类似与query,只是没有返回参数

 

 

 

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

下面的代码对HibernateDaoSupport类进行扩展(虽然Spring 2.0的HibernateTemplate提供了一个分页方法setMaxResults,但仅此一个方法依然不能实现分页查询),这种扩展主要是为该类增加了3个分页查询的方法,分页查询时必须直接调用Hibernate的Session完成,因此,必须借助于HibernateCallBack的帮助。

public class YeekuHibernateDaoSupport extends HibernateDaoSupport

{

    /**

     * 使用hql 语句进行分页查询操作

     * @param hql 需要查询的hql语句

     * @param offset 第一条记录索引

     * @param pageSize 每页需要显示的记录数

     * @return 当前页的所有记录

     */

    public List findByPage(final String hql, final int offset, final int pageSize)

    {

        //HibernateDaoSupport已经包含了getHibernateTemplate()方法

        List list = getHibernateTemplate().executeFind(new

        HibernateCallback()

            {

                public Object doInHibernate(Session session) throws HibernateException, SQLException

                //该方法体内以Hibernate方法进行持久层访问

                {

                    List result = session.createQuery(hql) .setFirstResult(offset) .setMaxResults(pageSize) .list();

                    return result;

                }

            });

        return list;

    }

    /**

     * 使用hql 语句进行分页查询操作

     * @param hql 需要查询的hql语句

     * @param value 如果hql有一个参数需要传入,value就是传入的参数

     * @param offset 第一条记录索引

     * @param pageSize 每页需要显示的记录数

     * @return 当前页的所有记录

     */

    public List findByPage(final String hql , final Object value , final int offset, final int pageSize)

    {

        List list = getHibernateTemplate().executeFind(new

        HibernateCallback()

            {

                public Object doInHibernate(Session session) throws HibernateException, SQLException

                {

                    //下面查询的是最简单的Hiberante HQL查询

                    List result = session.createQuery(hql) .setParameter(0, value) .setFirstResult(offset) .setMaxResults(pageSize) .list();

                    return result;

                }

            });

        return list;

    }

    /**

     * 使用hql 语句进行分页查询操作

     * @param hql 需要查询的hql语句

     * @param values 如果hql有多个参数需要传入,values就是传入的参数数组

     * @param offset 第一条记录索引

     * @param pageSize 每页需要显示的记录数

     * @return 当前页的所有记录

     */

    public List findByPage(final String hql, final Object[] values, final int offset, final int pageSize)

    {

        List list = getHibernateTemplate().executeFind(new

        HibernateCallback()

            {

                public Object doInHibernate(Session session) throws HibernateException, SQLException

                {

                    Query query = session.createQuery(hql);

                    for (int i = 0 ; i < values.length ; i++)

                    {

                        query.setParameter( i, values[i]);

                    }

                    List result = query.setFirstResult(offset) .setMaxResults(pageSize) .list();

                    return result;

                }

            });

        return list;

    }

}

在上面的代码实现中,直接使用了getHibernateTemplate()方法,这个方法由Hibernate- DaoSupport提供。而YeekuHibernateDaoSupport是HibernateDaoSupport的子类,因此,可以直接使用该方法。

当实现doInHibernate(Session session)方法时,完全以Hibernate的方式进行数据库访问,这样保证了Hibernate进行数据库访问的灵活性。

注意:Spring提供的XxxTemplate和XxxCallBack互为补充,二者体现了Spring框架设计的用心良苦:XxxTemplate对通用操作进行封装,而XxxCallBack解决了封装后灵活性不足的缺陷。

 

 

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

Spring和Hibernate集成的HibernateTemplate的一些常用方法总结

 

1:get/load存取单条数据

public Teacher getTeacherById(Long id) {  

    return (Teacher)this.hibernateTemplate.get(Teacher.class, id);  

}  

public Teacher getTeacherById(Long id) {  

    return (Teacher)this.hibernateTemplate.load(Teacher.class, id);  

}  

 

2:find/iterate查询操作

public Iterator getTeachersByAge(int age) {  

    Iterator iterator = null;  

      

    //使用find方法  

    List list = (List)this.hibernateTemplate().find("from Teacher t where t.age>?", new Integer(age));  

    iterator = list.iterator();  

      

    //使用iterator方法  

    iterator = this.hibernateTemplate().iterate("from Teacher t where t.age>?", new Integer(age));  

      

    return iterator;  

}  

find和iterato的区别主要是iterate采用了N+1次查询,对于大批量查询,比如查询10000条记录,那么iterate就要执行10000+1次查询,find和iterate应根据具体的实际

情况来使用,对于频繁的写操作对象,应使用find查询,而对于一些只读的数据对象,应使用iterate操作,因为iterate操作使用了Hibernate的缓存机制

 

3:save/update/saveOrUpdate/delete 保存/更新/删除操作  

public void save(Teacher teacher) {  

    this.hibernateTemplate.save(teacher);  

}  

public void update(Teacher teacher) {  

    this.hibernateTemplate.update(teacher);  

}  

public void update(Teacher teacher) {  

    this.hibernateTemplate.saveOrUpdate(teacher);  

}  

public void update(Teacher teacher) {  

    this.hibernateTemplate.delete(teacher);  

}  

 

4:bulkUpdate批量删除或者更新

bulkUpdate提供了批量删除和更新,直接转换为相应的update/delete SQL进行批量删除和更新

public void batchDelete(String name, int age) {  

    this.hibernateTemplate.bulkUpdate("delete Teacher where name=? and age = ?", new Object[]{name, age});  

}  

public void batchUpdate(String name, String newName) {  

    this.hibernateTemplate.bulkUpdate("update Teacher set name=? where name=?", new Object[]{newName, name});  

}  

此时要注意的一个问题是,使用bulkUpdate操作,必须手工清除相关对象在Hibernate中的缓存(包括一级缓存和二级缓存)

 

5:execute核心方法

public Object execute(HibernateCallBack action, boolean exposeNativeSession) throws DataAccessException {  

        Session session = getSession();  //获取一个Session  

        boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());  //当前session是否在事务中  

        FlushMode previousFlushMode = null;  

        try {  

            previousFlushMode = applyFlushMode(session, existingTransaction); //应用flush模式  

            enableFilters(session);  

              

            Session sessionToExpose = (exposeNativeSession? session: createSessionProxy(session));  //暴露给action的session  

            Object result = action.doInHibernate(sessionToExpose);  //执行action  

            flushIfNecessary(session, existingTransaction);  

            return result;  

              

        } catch(HibernateException ex) {  

            throw convertHibernateAccessException(ex);  

        } catch(SQLException ex) {  

            throw convertJdbcAccessException(ex);  

        } catch(RuntimeException ex) {  

            throw ex;  

        } finally {  

            if(existingTransaction) {  //如果session在事务中,则不关闭session  

                disableFilters(session);  

                if(previousFlushMode != null) {  

                    session.setFlushMode(previousFlushMode);  

                }  

            } else {  

                SessionFactoryUtils.releaseSession(session, getSessionFactory());  //释放session  

            }  

        }  

    }  

*HibernateCallBack,一般用来实现特定的业务逻辑

*exposeNativeSession:是一个布尔值,要暴露给HibernateCallBack实际的session对象,而不是一个代理过的对象

 

6:一般情况下,只有HIberateTemplate提供的方法不能满足要求时才使用execute方法,它的使用情况如下所示,

public void createDatabaseSchema() throws DataAccessException {  

    HibernateTemplate hibernateTemplate = new HibernateTemplate(this.sessionFactory);  

    //调用HibernateTempalte的execute方法  

    hibernateTemplate.execute(new HibernateCallback() {  

        public Object doInHibernate(Session session) throws HibernateException, SQLException {  //实现HibernateCallback的doInHibernate方法  

            //具体实现  

            Connection conn = session.connection();  

            final Dialect dialect = Dialect.getDialect(configuration.getProperties);  

            String[] sql = configuration.generateSchemaCreationScript(dialect);  

            executeSchemaScript(conn, sql);  

        }  

    });  

}  

使用execute方法的重点是实现HibernateCallback的doInHibernate方法,它会传递一个Session实例,可以使用此Session实例操作数据库,由此看出execute方法的好处是应用程序不用关心session的创建和释放,只需要处理关心的业务逻辑即可。

 

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

 

ref: 

http://www.blogjava.net/rain1102/articles/170638.html

http://blog.csdn.net/changewang/article/details/575191

http://yunqiang-zhang-hotmail-com.iteye.com/blog/1973010

http://www.linuxidc.com/Linux/2011-12/48719.htm

 

分享到:
评论

相关推荐

    HibernateCallback使用方法

    HibernateCallback 是 Hibernate 框架中的一种 callback 机制,允许开发者在持久层访问时执行自定义操作。HibernateCallback 是 Spring 框架中与 Hibernate 整合的重要组件,通过它可以实现灵活的持久层访问。 在 ...

    Hibernate3.6.10用到的jiar

    Hibernate3.6.10用到的jiar antlr-2.7.6.jar,commons-collections-3.1, commons-logging-1.1.3, dom4j-1.6.1, ejb3-persistence, hibernate-jpa-2.0-api-1.0.1.Final, hibernate3, javassist-3.12.0.GA, jta...

    hibernate执行原生sql语句

    在某些情况下,我们需要在 Hibernate DAO 中执行原生 SQL 语句,这时我们可以使用 `HibernateCallback` 接口来实现该功能。 例如,我们可以使用以下代码来执行一个原生 SQL 语句: ```java public Object ...

    Spring/泛型Hibernate的实现

    ### 泛型Hibernate的实现与Spring集成 #### 一、泛型Hibernate概念及其实现 在Java开发领域,尤其在企业级应用开发中,Hibernate框架因其强大的对象关系映射(ORM)能力而受到广泛欢迎。泛型Hibernate是利用Java...

    第24次课-1 Spring与Hibernate的整合

    Spring提供了org.springframework.orm.hibernate3.HibernateTemplate类和org.springframework.orm.hibernate3.HibernateCallback接口来方便和Hibernate整合。 HibernateTemplate类封装了Hibernate的主要类,它提供了...

    对hibernate的封装 HibernateTemplate

    6. **Callback机制**:通过HibernateCallback接口,可以在Hibernate Session内部执行自定义操作,保持事务的一致性。 **三、使用示例** 在使用HibernateTemplate之前,需要配置SessionFactory,并将其注入到...

    spring+hibernate详解

    本文详细介绍了Spring与Hibernate集成的过程,包括如何配置`SessionFactory`、使用`HibernateTemplate`简化数据操作、通过`HibernateDaoSupport`提高代码可维护性以及利用`HibernateCallback`实现更复杂的业务逻辑。...

    Hibernate学习笔记,使用Hibernate做数据层非常方便

    通过`getHibernateTemplate().executeFind()`方法,我们创建了一个`HibernateCallback`回调,内部执行SQL查询。这里使用了HQL(Hibernate Query Language)编写查询语句,`"from ControlScreen order by id desc"`...

    Spring整合Hibernate 详解.doc

    HibernateCallBack接口允许开发者在Hibernate操作的前后插入自定义的逻辑。通过实现这个接口,可以在执行特定数据库操作前后的回调函数中进行额外的工作,如事务控制、日志记录等。 6.5.6 使用IoC容器组装各种组件 ...

    Hibernate方法总结

    这是一个核心方法,它接受一个HibernateCallback接口的实例作为参数,允许在事务上下文中执行自定义的数据库操作。`execute`方法会确保在事务中执行回调方法,这样可以保证数据库操作的原子性。`exposeNativeSession...

    hibernate-distribution-3.6.8.Final

    它们可以通过继承Hibernate的`Serializable`接口或实现`HibernateCallback`接口来实现持久化。 5. **Session接口**:Session是Hibernate的主要工作单元,负责对象的持久化操作,如保存、更新、删除和查询。它是线程...

    struts2+spring+hibernate分页显示完整代码

    `queryForPage` 方法通过`getHibernateTemplate().executeFind()`方法执行HQL查询,并利用`HibernateCallback`接口回调来设置查询的起始位置和最大结果数,从而实现分页。`getAllRowCount` 方法则直接返回HQL查询后...

    Spring整合hibernate

    它通过回调机制(HibernateCallback)对Hibernate的操作进行封装,使开发者能够以一种更面向对象的方式处理数据库交互。例如,你可以通过实现HibernateCallback接口的doInHibernate方法,传入一个回调函数,执行特定...

    spring structs hibernate 整合

    此外,Spring还提供了HibernateTemplate和HibernateCallback接口,使得事务管理变得更加简单。在`applicationContext.xml`中,我们需要配置Hibernate的相关bean,如SessionFactory、DataSource等。 对于Struts和...

    spring整合hibernate

    3. **模板方法模式**:Spring 为 Hibernate 提供了三种主要的支持方式:`HibernateDaoSupport`、`HibernateTemplate` 和 `HibernateCallback` 接口。其中,`HibernateTemplate` 是一个非常实用的工具类,它可以简化 ...

    Struts+Spring+Hibernate之选课系统

    Spring还支持使用回调机制(如HibernateCallback)处理特殊查询和分页。 Hibernate的核心在于对象关系映射,它允许我们将Java对象直接映射到数据库表。开发者需要正确配置实体类(Entity)和数据访问对象(DAO),...

    struts2.3+spring3.1.2+hibernate4.1.6 配置说明

    值得注意的是,Hibernate 4.1.6版本不再包含`HibernateTemplate`、`HibernateCallback`以及`HibernateDaoSupport`等类。这些类在旧版本中用于简化数据库操作,但在新版本中,开发者需要进行相应的替换。例如,可以...

    HibernateS整合pring

    此外,`HibernateTemplate`还支持`HibernateCallback`接口,允许开发者在回调方法`doInHibernate(Session session)`中使用原生的Hibernate API,以应对更复杂的数据访问需求。这种方法确保了灵活性,即使在Spring的...

    基于hibernate实现的分页技术

    return this.getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery(...

    hibernate API

    虽然`HibernateTemplate`提供了很多便利,但它在处理复杂查询时可能需要创建内部类(inner class),如在分页查询时使用`execute(HibernateCallBack)`,这可能会增加调试的复杂性。相比之下,直接使用`Session`进行...

Global site tag (gtag.js) - Google Analytics