三、EJB使用JPA,Spring使用Hibernate
很多人都认为,在EJB 3中通过使用@PersistenceContext注释提供的entityManager对象来获得JPA的数据访问,而在Spring中,通过对SessionFactory对象的注入获得Hibernate数据访问。从而自然而然地认中,EJB使用JPA来操作数据对象,而Spring使用Hibernate来操作数据对象。
作为EJB3.0的一部分,JPA是一个好东西。其简单的配置方式及强大的默认配置支持,使其可以轻松自由的存在于轻量与重量之间。事实上,Spring同样支持使用JPA来操作数据对象(例如JpaTemplate),此外Spring提供了@PersistenceContext注释来支持JPA。在轻量级 Spring 框架的第二代中添加了一大批特性,即使是新的服务器应用程序开发人员也能够轻松上手。其关键增强之一就是 Spring 2 与JPA的集成。@PersistenceContext注释的使用示例如下面的代码所示:
package quickstart.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.transaction.annotation.Transactional; import quickstart.model.Person; @Transactional public class PersonServiceImpl implements PersonService { private EntityManager em; @PersistenceContext public void setEntityManager(EntityManager em) { this.em = em; } @SuppressWarnings("unchecked") public List<Person> findAll() { Query query = getEntityManager().createQuery("select p FROM Person p"); return query.getResultList(); } public void save(Person person) { if (person.getId() == null) { // new em.persist(person); } else { // update em.merge(person); } } public void remove(int id) { Person person = find(id); if (person != null) { em.remove(person); } } private EntityManager getEntityManager() { return em; } public Person find(int id) { return em.find(Person.class, id); } }
@PersistenceContext会让Spring在实例化的时候给服务注入一个EntityManager。@PersistenceContext注解可以放在实例变量,或者setter方法前面。如果一个类被注解为@Transactional,Spring将会确保类的方法在运行在一个事务中。
当 Spring JPA 应用程序在 Tomcat 上运行时,要让 JPA 支持正常工作,需要在类装入期间进行字节码“连接”。来自 Tomcat 的标准类装入器不支持这个,需要用特定于 Spring 的类装入器实现这个功能。要把这个特定于 Spring 的类装入器安装到 Tomcat 服务器,首先要把 spring-tomcat-weaver.jar 拷贝到 Tomcat 的 server/lib 子目录。这个目录包含的库属于 Tomcat 服务器私有,可以在 Spring 2 下载的 dist/weaver 目录下找到 spring-tomcat-weaver.jar 库。