Java Persistence API (JPA)
JPA 是个标准发布的JSR-220 (或 EJB3)的一部分. 大致与HIbernate或者Oracle的TopLink相同; 他们也是很多重要JPA的实现中的2个。. Guice 的持久化支持与厂商无关, 所以如果你需要的话它很容易在不同的实现(如Appengine's datastore)中进行切换。
启用持久化支持(Enabling Persistence Support)
简单的安装JPA模块(
JPA module)就可以启用持久化支持
Injector injector = Guice.createInjector(..., new JpaPersistModule("myFirstJpaUnit"));在JPA中, 在位于META-INF下配置你的persistence.xml文件,或者在classpath中(如果文件在jar中,那么此文件应该jar的根目录中) . 在这个文件中要大概的声明一些持久化单元,这些单元可能在不同的环境中(例如位于不同的数据库中),这里是一个简单的JPA配置的例子 :
<?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <!-- A JPA Persistence Unit --> <persistence-unit name="myFirstJpaUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <!-- JPA entities must be registered here --> <class>com.wideplay.warp.jpa.JpaTestEntity</class> <properties> <!-- vendor-specific properties go here --> </properties> </persistence-unit> </persistence>告诉Guice持久化模块你要使用哪些持久化单元,在创建你的模块时你需要指定这些单元的名称:
Injector injector = Guice.createInjector(..., new JpaPersistModule("myFirstJpaUnit"));最后,你必须决定持久化服务何时启动(调用PersistService的start()方法)。 .我通常用一个简单的启动类(initalizer)在我需要的时机来触发:
public class MyInitializer { @Inject MyInitializer(PersistService service) { service.start(); // At this point JPA is started and ready. } }
在你的应用中用Guice API启动所有的服务(service)非常有意义,建议您思考把它(启动持久化服务)如何应用到您特有的开发环境中。
不过,在web应用中,如果你使用PersistFilter 的话则不需要做其他事情(往下看)。
非常流行的策略是:
JPA
EntityManager创建和销毁于每个数据库事务中开始和结束点。在持久化单元的配置中设置
transaction-type属性:
<persistence-unit name="myFirstJpaUnit" transaction-type="RESOURCE_LOCAL">
在事务中使用EntityManager
一旦你注入器被创建,你以在你的持久化服务中任意注入和使用EntityManager :
import com.google.inject.persist.Transactional; import javax.persistence.EntityManager; public class MyService { @Inject EntityManager em; @Transactional public void createNewPerson() { em.persist(new Person(...)); } }
这是已知的session-per-transaction策略. 如果想了解更多关于事务和工作单元的信息,可以看“这里”.
注意:如果你为MyService加上 @Singleton注解,那么你需要使用Provider<EntityManager>方式进行注解来替换现在的方式。
Web环境(每请求一个会话) (session-per-http-request)
到此为止,我们已经看到
ssion-per-transaction策略。在web环境中这不是典型的方式,通常的方式是每个http请求为一个会话更好(也叫open-session-in-view).启用这种策略,你首先需要在ServletModule中增加一个filter:
public class MyModule extends ServletModule { protected void configureServlets() { install(new JpaPersistModule("myJpaUnit")); // like we saw earlier. filter("/*").through(PersistFilter.class); } }
你需要在加载使用
EntityManager
的其他模块之前首先加载这个filter。注意使用这个配置你可以使用同一个
EntityManager
运行多个事务(例如同一个Http请求)