2011-11-27 19 views
3

我有一個Persistence.xml存在多個持久性單元定義文件。相對持久單元注入?

我想根據進入系統的用戶注入單元EntityManager對象。

可能嗎?

@PersistenceContext (unitName = myUnit) 

在此使用,我得到一個警告: 「屬性值必須是常量」

應用框架:JSF 2.1 &春3.0.2

持久層:JPA

回答

1

由於錯誤消息說,Java註釋屬性必須是常量值,而不是對變量的引用。這是Java語言中的一個限制,而不是JPA。你需要找到一種不同的方式去做你想做的事情。

+0

最終變量無法找出這個問題。 你能建議我一個不同的可以找到? – hakdogan

+1

最終變量!=常數 – skaffman

+0

我想說 private String unit =「myUnit」; private final String unitNanme = unit; @PersistenceContext(unitName = unitNanme) private EntityManager em; – hakdogan

1

正如在另一篇文章中提到的,註釋屬性必須是常量。

另一種方法可以編程得到一個EntityManager實例:

Persistence.getEntityManagerFactory().getEntityManager(persistenceUnitName); 

您可以實現分配取決於你自己的標準持久性單元名稱所必需的邏輯。顯然,這與持久性不再由容器管理的事實相關。

+0

謝謝。 很顯然,我想留下持久性上下文關係的春天。 – hakdogan

+0

所以你想在運行時定義你想使用的PersistenceContext並讓Spring解決它? –

+0

Piotr Nowicki,我想在運行時定義PersistenceContext並使用並讓Spring解決它。 – hakdogan

2

你可以使用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 SE自舉的API的使用可以用Java EE容器的支持;然而,不需要支持這種使用。

此外,我認爲創建一個新的EntityManagerFactory可能會很慢;您可能會發現需要緩存查找結果。我相信應該很長時間堅持一個EntityManagerFactory,並從多個線程訪問它(但我不確定)。

+0

我認爲這是正確的方向。儘管如此,我不確定Spring是否會自帶實現'@Inject'和其他註釋。不知道它將如何合作... –

+0

啊,我錯過了你使用春天,對不起。我相信Spring有它自己的@Produces的等價物 - 你應該可以使用它來實現相同的模式。 –

+0

嗨湯姆安德森。 建議的方法,當有固定數量的單位可用時。 我的系統上的單元數目不穩定,可隨時增加,而且我不想幹擾java。 – hakdogan

0

我達成了解決方案。我是Spring的新人。確實有更好的解決方案,但我仍然想分享解決方案。

的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(); 
    } 
} 
0

我的解決方案是解決不了問題:)

的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發生。試圖減慢項目。

我正在尋找一種有效的解決方案。

謝謝。