1.LocalEntityManagerFactoryBean
只是簡單環境中使用。它使用JPA PersistenceProvider自動檢測機制( according to JPA's Java SE bootstrapping ),並且大多數情況下,你只能定義一下persistence unit name
例如:
<beans> <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="myPersistenceUnit"/> </bean> </beans>
2.從JNDI獲取EntityManagerFactory
這個選項是當你應用發布在javaee5的服務器中。你可以參閱自己應用服務器文檔,如何發布一個自定義的JPA provider到你的應用服務器中。
例:
<beans> <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/> </beans>
當javaee服務器啟動時,會自動檢測persistence units。實際上,是檢測應用包中的META-INF/persistence.xml 文件和web.xml中的persistence-unit-ref,以及定義的environment naming。我理解就是JNDI的name。
一般應用情景是:
在META-INF/persistence.xml中 使用<jta-data-source>java:/ MySqlDS</jta-data-source> 獲取容器發布的Datesource。
transactions是使用的javaee容器支持的JTA系統,例如tomcat中,可以這樣
3.LocalContainerEntityManagerFactoryBean
這個選項中,spring扮演了容器的角色。完全掌管JPA。
LocalContainerEntityManagerFactoryBean會根據persistence.xml創造一個PersistenceUnitInfo實現。
<beans>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="someDataSource"/>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
</beans>
不是所有的JPA provider都需要load-time weaving。hibernate就不需要。呵呵。 <property name="loadTimeWeaver">這個就不是必須的了。。
Persistence.xml配置:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL"> <mapping-file>META-INF/orm.xml</mapping-file> <exclude-unlisted-classes/> </persistence-unit> </persistence>
如何處理多個persistence units。spring提供了PersistenceUnitManager統一管理。
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
<value>classpath:/my/package/**/custom-persistence.xml</value>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="localDataSource" value-ref="local-db"/>
<entry key="remoteDataSource" value-ref="remote-db"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum"/>
<property name="persistenceUnitName" value="myCustomUnit"/>
</bean>
dataSources中的key是persistence.xml中配置的datasource名字,value-ref是spring管理的數據源。
另外:
EntityManagerFactory是線程安全的,但是EntityManager不是。
public class ProductDaoImpl implements ProductDao { private EntityManagerFactory emf; @PersistenceUnit public void setEntityManagerFactory(EntityManagerFactory emf) { this.emf = emf; } public Collection loadProductsByCategory(String category) { EntityManager em = this.emf.createEntityManager(); try { Query query = em.createQuery("from Product as p where p.category = ?1"); query.setParameter(1, category); return query.getResultList(); } finally { if (em != null) { em.close(); } } } }
這樣使用有個最大問題就是每次都要創建一個新的entityManager。那么該怎么辦?
你可以通過@PersistenceContext獲取一個transactional EntityManager("shared EntityManager")。為什么稱它為transactional?因為它是一個共享的以及線程安全的當前的transactional EntityManager的一個代理。
public class ProductDaoImpl implements ProductDao { @PersistenceContext private EntityManager em; public Collection loadProductsByCategory(String category) { Query query = em.createQuery("from Product as p where p.category = :category"); query.setParameter("category", category); return query.getResultList(); } }
結束了。
