java - 动态创建EntityManager

标签 java jpa ejb

我的问题其实很简单,但我确实没有找到好的解决方案。

我目前在我的应用程序中管理多个数据库:

  • 一个唯一的管理数据库(具有静态名称);
  • 一个客户端数据库,其名称取决于客户端。

我正在使用 JPA,我想为客户端数据库动态创建 EntityManager。但是当我以编程方式创建它时,我收到此错误: javax.persistence.TransactionRequiredException:已在无法注册 JTA 事务的资源本地 EntityManager 上调用 joinTransaction。

这是代码:

@Stateful
public class ServiceImpl implements Service{

private EntityManagerFactory emf;
private EntityManager em;

@PostConstruct      // automatically called when EJB constructed and session starts
public void init() {
    emf = Persistence.createEntityManagerFactory("punit");
    em = emf.createEntityManager();
}
...

@Stateful(mappedName = "CustomerService")
public class CustomerServiceImpl extends ServiceImpl implements CustomerService {

@Override
public void create(Customer cust) {
    getEm().joinTransaction();
    getEm().persist(cust);
}

更一般地说,我在使用 JPA 时遇到了问题。我只想连接到两个数据库,对它们进行一些 CRUD 操作。但我真的不知道如何管理事务(我的第一个方法是让容器来管理它......)。

如果有人可以帮助我,那就太好了!

注意:我正在使用 Glassfish Java EE 服务器和 PGSql DB。

最佳答案

在jpa中,可以在persistence.xml文件中声明多个prsistenceunit。

在注入(inject)时,您可以执行以下操作:

@PersistenceContext(unitName = "unitName0", properties={@PersistenceProperty(...)}
EntityManager emClient;

@PersistenceContext(unitName = "unitName1", properties={@PersistenceProperty(...)}
EntityManager emAdmin;

这样,您就不必手动创建实体管理器,因此您可以获得容器事务管理。

未测试:

如果您有动态数据库名称,您将注入(inject) EntityManagerFactory

@PersistenceContext(unitName ="名称") EntityManagerFactory emf;

//在你想要EntityManager的时候

Map<String, String> props; //put the connection property for the EM here
EntityManager em = emf.createEntityManager(props);

基于在J2EE环境中我们使用DataSources和ConnectionPooling的概念,如果不手动创建entitymanagerfactory,几乎不可能实现这种动态数据源。

这是我的推理: 服务器管理连接池,jpa 提供程序(例如 eclipselink)使用 jndi 来确定与数据库的连接。这意味着如果您要更改数据库名称,那么它还必须具有连接池资源和关联的 jdbc 资源。这当然会否定你想做的事情。

基本解决方案:手动创建EntityManagerFactory并手动管理事务。 在持久性 xml 中指定该单元是非 jta 才能正常工作。

然后您可以根据用户 session 以编程方式提供连接数据:

类似的事情:

//这必须是特定于 session 的。

class PersistenceSession{
  static Map<String, String> clientSessionProps;

  //When new session starts and a new client has logged in.
  static void setClientConnectionProperties(Client client){
    .....
  }

  static Map<String, String> getClientSessionProps(){
   return clientSessionProps;
  }
}

在 ejb 级别。

@Stateless
   public class TestEntityFacade extends AbstractFacade<TestEntity> {


    private EntityManagerFactory emf;

    @PostConstruct
    void init(){
      emf = Persistence.createEntityManagerFactory("name");
    }

    @Override
    protected EntityManager getEntityManager() {
            return emf.createEntityManager(PersistenceSession.getClientSessionProps());
    }

    public TestEntityFacade() {
        super(TestEntity.class);
    }

     void add(Entity e){

        EntityManager em = getEntityManager();
        em.getTransaction().begin();
        .....
        em.getTransaction().commit();
    }

}

关于java - 动态创建EntityManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24572705/

相关文章:

java - 从 GSON 解析 JSON 中的通用标签

java - JMM 中的因果关系要求

java - 仅当通过 JAX-RS 调用时才出现 Hibernate 错误

@Asynchronous bean 中的 Java 注入(inject)

java - 并发访问 @Lock(LockType.WRITE) 方法

java - JAXB - 对动态标签名称使用继承

java - '{}' 中的主类 block 从不执行

java - Hibernate with jpa 不会在 Wildfly 中自动创建表

java - 使用 Sniffy 指定的 Oracle URL 无效

java - 使用@ejb 注释进行远程查找