相对持久性单元注入?

发布于 2024-12-18 09:56:36 字数 252 浏览 1 评论 0原文

我有一个包含多个持久性单元定义文件的 Persistence.xml。

我想根据进入系统的用户注入单元EntityManager对象。

是否可以?

@PersistenceContext (unitName = myUnit)

在这种使用中,我收到警告:“属性值必须是常量”

应用程序框架:JSF 2.1 & Spring 3.0.2

持久层:JPA

I have a Persistence.xml with multiple persistence-unit definition file exists.

I want to inject unit EntityManager object, according to the user who entered the system.

Is it possible?

@PersistenceContext (unitName = myUnit)

In this use, I get a warning: "attribute value must be constant"

Application Frameworks: JSF 2.1 & Spring 3.0.2

Persistence layer: JPA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

春庭雪 2024-12-25 09:56:37

可以使用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 应用程序中工作,< a href="http://docs.oracle.com/javaee/6/api/javax/persistence/Persistence.html#createEntityManagerFactory%28java.lang.String%29" rel="nofollow">Persistence.createEntityManagerFactory 不保证在 J2EE 中工作。规范中的脚注 42(至少是 EJB 3.0 持久性规范)说:

Java EE 容器可能支持使用这些 Java SE 引导 API;但是,不需要支持此类使用。

此外,我相信创建一个新的 EntityManagerFactory 可能会非常慢;您可能会发现需要缓存查找结果。我相信长时间持有 EntityManagerFactory 并从多个线程访问它应该是安全的(但我不确定)。

Can you use CDI? You could write a little class which gets injected with all the different contexts, then supplies them to your classes through a producer method which does some logic. Bit like this:

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
        }
    }
}

Then you can just write classes like this:

public class FeedReamer {
    @Inject private EntityManager em;
}

And everything will magically happen right (possibly?).

If you don't want to hardcode the names of the persistence units in the class, then instead of relying on injection, you may be able to get the entity manager factories explicitly:

    @Produces
    public EntityManager getEntityManager(InjectionPoint ip) {
        String persistenceUnitName = somehowDeterminePersistenceUnitName();
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
        return emf.createEntityManager();
    }

However, although this method will work in a J2SE application, Persistence.createEntityManagerFactory is not guaranteed to work in J2EE. Footnote 42 in the spec (the EJB 3.0 persistence spec, at least) says:

Use of these Java SE bootstrapping APIs may be supported in Java EE containers; however, support for such use is not required.

In addition, i believe that creating a new EntityManagerFactory can be quite slow; you might find you needed to cache the results of the lookups. I believe it should be safe to hold on to an EntityManagerFactory for a long time, and to access it from multiple threads (but i'm not certain).

那小子欠揍 2024-12-25 09:56:37

正如错误消息所示,Java 注释属性必须是常量值,而不是对变量的引用。这是 Java 语言的限制,而不是 JPA 的限制。您需要找到一种不同的方式来完成您想做的事情。

As the error message says, Java annotation attributes must be constant values, not references to variables. This is a limitation in the Java languages, not JPA. You'll need to find a different way to do what you're trying to do.

毁梦 2024-12-25 09:56:37

正如另一篇文章中提到的,注释属性必须是常量。

另一种方法可能是以编程方式获取 EntityManager 实例:

Persistence.getEntityManagerFactory().getEntityManager(persistenceUnitName);

您可以根据自己的条件实现分配持久性单元名称所需的逻辑。显然,这具有与持久性不再由容器管理这一事实相关的所有缺点。

As it has been mentioned in another post, annotation attributes must be constant.

Another approach could be getting an EntityManager instance programmatically:

Persistence.getEntityManagerFactory().getEntityManager(persistenceUnitName);

You could implement the logic necessary to assign the persistence unit name depending on your own criteria. Obviously this has all the downsides associated to the fact that persistence is not managed by the container anymore.

吖咩 2024-12-25 09:56:37

我达成了解决方案。我是春天的新学习者。肯定有更好的解决方案,但我仍然想分享解决方案。

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

I reached a solutions. I'm new learning in Spring. There are definitely better solutions, but I still wanted to share the solution.

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(); 
   } 
} 
灯下孤影 2024-12-25 09:56:37

我的解决方案不是解决方案:)

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 的发生。试图减慢项目进度。

我正在寻找春季有效的解决方案。

谢谢。

My solution was not the solution :)

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

Does not have a property such as LocalEntityManagerFactoryBean persistenceUnitManager. For this reason, I could not set the names of unit.

The cost is to create EntityManagerFactory in happening. Trying to slow the project.

I'm looking for an effective solution in the Spring.

Thanks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文