【发布时间】:2011-11-27 19:50:29
【问题描述】:
我有一个包含多个持久性单元定义文件的 Persistence.xml。
我要根据进入系统的用户注入单元EntityManager对象。
有可能吗?
@PersistenceContext (unitName = myUnit)
在这个使用中,我得到一个警告:“属性值必须是常数”
应用程序框架:JSF 2.1 和 Spring 3.0.2
持久层:JPA
【问题讨论】:
标签: java jpa annotations
我有一个包含多个持久性单元定义文件的 Persistence.xml。
我要根据进入系统的用户注入单元EntityManager对象。
有可能吗?
@PersistenceContext (unitName = myUnit)
在这个使用中,我得到一个警告:“属性值必须是常数”
应用程序框架:JSF 2.1 和 Spring 3.0.2
持久层:JPA
【问题讨论】:
标签: java jpa annotations
您可以使用 CDI 吗?您可以编写一个注入所有不同上下文的小类,然后通过执行一些逻辑的生产者方法将它们提供给您的类。有点像这样:
public class PersistenceContext {
@PersistenceContext(unitName="myUnit") private EntityManager myEm;
@PersistenceContext(unitName="yourUnit") private EntityManager yourEm;
@Produces
public EntityManager getEntityManager(InjectionPoint ip) {
if (USER IS ME) {
return myEm;
}
else if (USER IS YOU) {
return yourEm;
}
else {
NOW PANIC AND FREAK OUT
}
}
}
然后你可以像这样编写类:
public class FeedReamer {
@Inject private EntityManager em;
}
一切都会神奇地正确发生(可能?)。
如果您不想硬编码类中持久性单元的名称,那么您可以显式获取实体管理器工厂,而不是依赖注入:
@Produces
public EntityManager getEntityManager(InjectionPoint ip) {
String persistenceUnitName = somehowDeterminePersistenceUnitName();
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
return emf.createEntityManager();
}
但是,尽管此方法可以在 J2SE 应用程序中工作,但不能保证 Persistence.createEntityManagerFactory 在 J2EE 中工作。规范中的脚注 42(至少是 EJB 3.0 持久性规范)说:
Java EE 容器可能支持使用这些 Java SE 引导 API;但是,不需要支持此类使用。
另外,我相信创建一个新的 EntityManagerFactory 会很慢;您可能会发现需要缓存查找结果。我相信长时间持有 EntityManagerFactory 并从多个线程访问它应该是安全的(但我不确定)。
【讨论】:
@Inject 和其他注释。想知道它将如何合作......
正如错误消息所说,Java 注释属性必须是常量值,而不是对变量的引用。这是 Java 语言的限制,而不是 JPA。你需要找到一种不同的方式来做你想做的事情。
【讨论】:
正如在另一篇文章中提到的,注释属性必须是常量。
另一种方法可能是以编程方式获取 EntityManager 实例:
Persistence.getEntityManagerFactory().getEntityManager(persistenceUnitName);
您可以根据自己的标准实现分配持久性单元名称所需的逻辑。显然,这具有与容器不再管理持久性相关的所有缺点。
【讨论】:
我找到了解决方案。我是春天的新手。肯定有更好的解决方案,但我仍然想分享解决方案。
applicationContext.xml
<context:component-scan base-package="com.hakdogan.hakdoganjsfspring"/
<tx:annotation-driven transaction-manager="transactionManagerConstant"/
<tx:annotation-driven transaction-manager="transactionManagerRelative"/
<bean id="odev" class="com.hakdogan.hakdoganjsfspring.entity.Nesne" /
<bean id="transactionManagerConstant"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="constant"/>
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="transactionManagerRelative"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="relative"/>
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="jpaDialect"
class="com.hakdogan.hakdoganjsfspring.util.HibernateExtendedJpaDialect" /
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitMa nager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
<value>classpath*:META-INF/hk.xml</value>
</list>
</property>
</bean>
<bean id="constant"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager"
ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="JSFSpring" />
</bean>
<bean id="relative"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager"
ref="persistenceUnitManager" />
</bean>
<bean id="persistenceManager"
class="com.hakdogan.hakdoganjsfspring.util.PersistenceManager"/>
</beans>
PersistenceManager.java
public class PersistenceManager {
private LocalContainerEntityManagerFactoryBean persistence;
public LocalContainerEntityManagerFactoryBean getPersistence() {
return persistence;
}
@Autowired
@Qualifier("relative")
public void setPersistence(LocalContainerEntityManagerFactoryBean
persistence) {
this.persistence = persistence;
}
}
PersistDAO.java
@Component("persistDAO")
@Scope("session")
public class PersistDAO {
@PersistenceContext(unitName="JSFSpring")
private EntityManager em;
@Autowired
private PersistenceManager persistenceManager;
@Autowired
private Nesne nesne;
private List<Odev> kayitListesi;
private List<Event> eventListesi;
private String myUnit = "hakdogan";
public Nesne getNesne() {
return nesne;
}
public void setNesne(Nesne nesne) {
this.nesne = nesne;
}
@Transactional(isolation = Isolation.SERIALIZABLE, propagation =
Propagation.REQUIRED)
public String kaydet(){
em.persist(nesne);
return "/liste.xhtml";
}
@Transactional(propagation = Propagation.REQUIRED, readOnly=true)
public List<Odev> getKayitListesi() {
return kayitListesi = (List<Odev>)
em.createNamedQuery("Odev.findAll").getResultList();
}
@Transactional(readOnly=true)
public List<Event> getEventListesi() {
persistenceManager.getPersistence().setPersistenceUnitName(myUnit);
EntityManager emt = persistenceManager.getPersistence().getNativeEntityManagerFactory().createEntityManager();
return eventListesi = (List<Event>)
emt.createNamedQuery("Event.findAll").getResultList();
}
}
【讨论】:
我的解决方案不是解决方案:)
applicationContext.xml:
<context:component-scan base-package="com.hakdogan.hakdoganjsfspring"/>
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManagerConstant"/>
<tx:annotation-driven transaction-manager="transactionManagerRelative"/>
<bean id="jpaDialect" class="com.hakdogan.hakdoganjsfspring.util.HibernateExtendedJpaDialect" />
<bean id="transactionManagerConstant" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="constant"/>
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="transactionManagerRelative" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="relative"/>
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="constant" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="JSFSpring" />
</bean>
<bean id="relative" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="persistenceUnitName" value="hakdogan" />
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</bean>
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
</bean>
<bean id="persistenceManager" class="com.hakdogan.hakdoganjsfspring.util.PersistenceManager"/>
<bean id="odev" class="com.hakdogan.hakdoganjsfspring.entity.Odev" scope="prototype" />
</beans>
PersistenceManager.java:
public class PersistenceManager {
@Autowired
private LocalEntityManagerFactoryBean persistence;
private PersistenceProvider provider;
public EntityManager getBaglam(String unitName){
if(null == provider)
provider = persistence.getPersistenceProvider();
if(!unitName.equals(persistence.getPersistenceUnitName()))
persistence.setPersistenceUnitName(unitName);
return provider.createEntityManagerFactory(unitName, null).createEntityManager();
}
}
PersistDAO.java:
@Component("persistDAO")
@Scope("session")
public class PersistDAO {
@PersistenceContext(unitName="JSFSpring")
private EntityManager em;
@Autowired
private PersistenceManager persistenceManager;
private List<Odev> kayitListesi;
private List<Event> eventListesi;
private List<Musteriler> musteriListesi;
private String myUnit = "hakdogan";
@Transactional(propagation = Propagation.REQUIRED, readOnly=true)
public List<Odev> getKayitListesi() {
return kayitListesi = (List<Odev>) em.createNamedQuery("Odev.findAll").getResultList();
}
@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED)
public List<Event> getEventListesi() {
return persistenceManager.getBaglam(myUnit).createQuery("SELECT e FROM Event e").getResultList();
}
@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED)
public List<Musteriler> getMusteriListesi() {
return persistenceManager.getBaglam("musteri").createNamedQuery("Musteriler.findAll").getResultList();
}
}
没有 LocalEntityManagerFactoryBean persistenceUnitManager 等属性。由于这个原因,我无法设置单位的名称。
成本是在发生时创建 EntityManagerFactory。试图减慢项目的速度。
我正在寻找春季有效的解决方案。
谢谢。
【讨论】: