使用Session
关于这一点,你可以参考关于Hibernate和持久层的文章或者指南,也可以查询各种对象和实例来了解怎么使用事务,所以我不打算详细说这些内容。相反,我会更多考虑使用实体后我们需要做什么?这会对Hibernate Session 对象有怎样的影响?是否可以使用现有的业务对象,甚至是数据访问对象?当我建立数据层的时候,我使用了Spring及其提供的一些类来管理数据库连接,事务和会话。这些对象都在XML配置文件里面定义了,并与很多规则和关系紧密集成在Spring里。首先,通过Spring的依赖注射,DAO对象会被引入到应用服务中(关于依赖注射,参见Bruce Tate的《Five Things I Love About Spring》一书)。然后,配置应用服务以捕获DAO异常(通过XML配置文件),让Spring去处理。可是因为我觉得把Spring集成到数据加载应用里会带来相当大的工作量。我对DAO对象做了轻微的修改,使得可以在web应用之外使用他们。
例如说在PersonDAO类里面有一个保存person对象的方法。如果Hibernate Session 是由容器建立的,那这个方法就不能在容器外使用,因为这需要一个配置好的Session对象。以下是一个典型的PersonDAO,它由Spring 容器提供了对Session的支持。
清单6:
| import org.springframework.orm.hibernate.HibernateTemplate; import test.pojos.Person; public class PersonDAO extends HibernateTemplate { public PersonDAO(){} public Person save(Person aPerson) { if(aPerson != null) super.save(person); return person; } } |
上面的类继承的是Spring HibernateTemplate 类,它提供了各种不错的使用Hibernate的基类方法。而且由于HibernateTemplate类维护了大多数的常见操作,你就只需要专注特定的持久层需求。当然也应该有相应的异常处理,但在本次范例当中,只要以上的就够了。
现在,要在容器外加上对Session的支持,我们只需要做一些小小的改动:
清单7:
| import org.springframework.orm.hibernate.HibernateTemplate; import net.sf.hibernate.Session; import test.pojos.Person; public class PersonDAO extends HibernateTemplate { public PersonDAO(){} public void setExternalSessionFactory(Session aSession){ setSessionFactory(session.getSessionFactory()); } public Person save(Person aPerson) { if(aPerson != null) super.save(person); return person; } } |
因为HibernateTemplate类继承于HibernateAccessor类,我们就可以从任何Session对象中建立SessionFactory。这是Spring小组的一个高灵活性的设计,使得重用现有代码更加容易。
也许你并没有使用Spring而是采用完全不同的方法。如果你不喜欢Spring的一来注射,你也可以通过JNDI查找Session对象:
清单8:
| import net.sf.hibernate.Session;public class PersonDAO { // This example assumes that there is a Hibernate // Session object at the following JNDI location // on a Tomcat 5.5 server: // java:/comp/env/obj/hibernateSession private Session session; public PersonDAO(){ try { Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); session = (Session)envCtx.lookup("obj/hibernateSession"); }catch(Exception e) { e.printStackTrace(); } } public Person save(Person aPerson) { if(aPerson != null) session.save(person); return person; } } |
以上的例子依赖于应用服务器来使得Hibernate Session对象可用。在容器之外使用的最简单方法就是添加一个带Session参数的构造函数,如下所示:
清单9:
| import net.sf.hibernate.Session; public class PersonDAO { // This example assumes that there is a Hibernate // Session object at the following JNDI location // on a Tomcat 5.5 server: // java:/comp/env/obj/hibernateSession private Session session; public PersonDAO(){ try { Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); session = (Session)envCtx. lookup("obj/hibernateSession"); }catch(Exception e) { e.printStackTrace(); } } public PersonDAO(Session aSession){ session = aSession; } public Person save(Person aPerson) { if(aPerson != null) session.save(person); return person; } } |
当然我们并没有处理太多的异常,事务问题。甚至我们在多个方法内共用一个Session对象,这会导致一些并发事务问题(取决于容器或框架如何处理对象实例)。不过我想很显然以上的例子演示了如何重用大量的现有数据层代码。只需要一点点有创造力的想法。要弄清楚你是否想在应用服务器之外使用现有的实体和DAO,接下来就不断尝试把。
结论
正如你所见,要在web容器外使用Hibernate 实体和DAO是需要技巧的,但这肯定能做到的。最大的困难在于如何查找实体映射关系和如何重设置(或者说修改)现有的数据访问对象(即DAO)。处理后者时,要小心处理事务问题,因为没有应用服务可以依赖了。不过最后,我们还是可以访问所有的实体和进行持久化的对象,这样能省下大量的重新开发代码的时间。祝您好运!!








