读书人

Spring数据库访问之ORM(2)

发布时间: 2012-09-24 13:49:41 作者: rapoo

Spring数据库访问之ORM(二)
本文接上一篇继续来研究Spring的ORM模块。
现在我们来看如何在Spring中配置ORM资源工厂,也就是在Spring中使用ORM框架。仍然以Hibernate为例来说明,要引入spring-orm和spring-context模块来做测试。首先我们可以修改一下DAO实现类的写法,因为用了Spring,就不用显式来new对象了,那么对于Hibernate的SessionFactory,使用注入的方式来进行配置,修改CourseDAOImpl类,如下设置:


把Hibernate配置对象的映射文件加上,之后修改测试方法,从Spring的容器中获取对象就可以了:

将数据库的基本信息配置好后,数据源的配置就完成了。下面是配置Hibernate:

这里我们将实体映射一起配置进来,使用了*通配符,并配置了基本的Hibernate属性,比如方言,显示sql语句和自动建表。剩下的就是DAO的配置了,它不用做什么修改,仍然注入sessionFactory即可,然后执行测试:

从中可以看到启动信息和Hibernate生成的SQL语句。除了使用Hibernate的实体映射文件外,我们还可以使用注解,之前已经在Course持久化类中添加了注解,那么我们就来配置使用注解的方式,很简单,只需修改Spring中的Hibernate SessionFactory配置即可,如下:

这样就使用在持久化类中的注解信息而不需要单独编写HBM映射文件了,执行测试,结果是一样的。当然,在Spring中,还可以使用JPA的EntityManager来进行数据的持久化操作,那么又如何来进行呢?和前面介绍的类似,首先在JPA的DAO实现类中修改EntityManager的配置方式,使用注入来进行:

因为配置了persistenceUnitName,那么不要忘记了在META-INF目录下的persistence.xml文件,其中是这么写的:

因为还用到了hibernate.cfg.xml,不过要将mapping的映射信息全部去掉,之后的courseDaoJPA配置就很简单了:

在测试程序的ctx.getBean方法中换成courseDaoJPA就可以获得JPA的DAO实现对象了,从而进行数据库操作,这也非常简单。如果不使用hibernate的配置文件,那么需要对JPA进行如下的配置:

将数据源注入进来,并配置一些数据库方言,显示sql和生成ddl的信息,最后精简一下persistence.xml文件中的内容:

已经不需要再使用Hibernate的配置文件了,这样就可以了,再次执行测试程序,就可以得到如下输出信息:

在JDBC模块中,Spring的JDBC模板简化了SQL的操作,使得使用SQL非常简便,不需要很多的代码就能完成数据库操作,同样,在ORM模块中,Spring的模板技术也有应用,这里我们主要来看Hibernate模板和JPA模板技术。使用HibernateTemplate非常简单,在DAO的实现类中进行注入即可,使用Hibernate模板为我们提供的方法来执行ORM操作,非常的简便:

使用tx前缀,只需加上相应的命名空间说明即可,这也很简单。修改主程序:

相对于HibernateTemplate,JpaTemplate也可以实现相同功能,我们来看如下代码:

这样,我们修改测试程序中getBean获得的对象,就可以测试程序了,这都非常简单了。这里我们扩展说一点,使用了HibernateTemplate或jpaTemplate后,如果想获取Session或EntityManager,那么可以这么操作:hibernateTemplate.getSessionFactory().getCurrentSession(),对于JPA则是:jpaTemplate.getEntityManager(),除此之外,我们还可以使用他们的execute()方法来执行操作:

当然,也可以给该类注入HibernateTemplate,看一下该类的源码即可参照使用对应的实例进行注入了,这都很简单,JPA的修改也是相似的:

下一篇将继续介绍Spring对ORM的支持。 1 楼 ceci.lia 2011-03-07 引用对于JPA则是:jpaTemplate.getEntityManager()这句应该是不对的。JpaTemplate.getEntityManager只会返回null,如果在xml中配置了entityManager的依赖,就能正确返回。这是因为实现getEntityManager的JpaAccessor类只会返回注入的EntityManager的实例。而HibernateTemplate中实现了getSession的方法,所以才可以返回。从我看到的API来看,貌似EntityManager被限制在Spring的框架中。当然除非通过EntityManagerFactory来创建EntityManager的实例,获取继承JpaTemplate来获得对EntityManagerFactoryAccessor中的getTransactionalEntityManager方法的调用

2 楼 sarin 2011-03-07 ceci.lia 写道引用对于JPA则是:jpaTemplate.getEntityManager()这句应该是不对的。JpaTemplate.getEntityManager只会返回null,如果在xml中配置了entityManager的依赖,就能正确返回。这是因为实现getEntityManager的JpaAccessor类只会返回注入的EntityManager的实例。而HibernateTemplate中实现了getSession的方法,所以才可以返回。从我看到的API来看,貌似EntityManager被限制在Spring的框架中。当然除非通过EntityManagerFactory来创建EntityManager的实例,获取继承JpaTemplate来获得对EntityManagerFactoryAccessor中的getTransactionalEntityManager方法的调用


是我没有说清楚,之前的配置有了,那么后面为了省略就没有再提,可能对于不了解的人会产生误解。也感谢您的说明。 3 楼 ceci.lia 2011-03-08 sarin请教一下:你说的配置是EntityManager的配置?还是EntityManagerFactory的配置?

如果直接注入EntityManager实例到IoC容器并且配置依赖,那么getEntityManager就不会返回空。如果只是配置了EntityManagerFactory的依赖,那么getEntityManager依然会返回为空。Spring没有像HibernateTemplate的getSession方法那样实现。

对于直接注入JpaTemplate实例没有测试过,应该也是不行的。

这是Spring框架对于JPA实现存在不完整的情况。还望sarin兄帮忙确认下?
4 楼 sarin 2011-03-08 persistence-unitceci.lia 写道sarin请教一下:你说的配置是EntityManager的配置?还是EntityManagerFactory的配置?

如果直接注入EntityManager实例到IoC容器并且配置依赖,那么getEntityManager就不会返回空。如果只是配置了EntityManagerFactory的依赖,那么getEntityManager依然会返回为空。Spring没有像HibernateTemplate的getSession方法那样实现。

对于直接注入JpaTemplate实例没有测试过,应该也是不行的。

这是Spring框架对于JPA实现存在不完整的情况。还望sarin兄帮忙确认下?

配置EntityManagerFactory 配置persistence-unit,若使用ORM框架,还是Hibernate为好,毕竟JPA底层还是参考了Hibernate。
整理时我没有发现不完整的地方,二者都是对比说明的,而且所有测试全部通过。 5 楼 ceci.lia 2011-03-08 如果调用getJpaTemplate().getEntityManager.merge(course),就应该有问题了。会抛出NullPointerException,这是我这里抛出的问题。
不过还是感谢sarin的耐心回答。
哎,没办法了,还是用JPA的@PersistenceContext的annotation来设置EntityManager的实例了。 6 楼 sarin 2011-03-08 ceci.lia 写道如果调用getJpaTemplate().getEntityManager.merge(course),就应该有问题了。会抛出NullPointerException,这是我这里抛出的问题。
不过还是感谢sarin的耐心回答。
哎,没办法了,还是用JPA的@PersistenceContext的annotation来设置EntityManager的实例了。
空指针的问题应该还是在哪块儿没有生成对象,所以引用不到,Spring中一定要注入进来。可能很小的地方我们忽略了。

读书人网 >其他数据库

热点推荐