【问题标题】:How can I create a JTA-aware EntityManager in WebLogic 12c with a data-source not known at compile time?如何在 WebLogic 12c 中使用编译时未知的数据源创建可识别 JTA 的 EntityManager?
【发布时间】:2015-10-07 10:20:14
【问题描述】:

我正在开发一个要部署在 WebLogic 12c 中的应用程序,它需要能够在运行时获得连接到任意数据源的 JPA EntityManager (EclipseLink 2.5.2)。我目前不知道该数据源的 JNDI 名称是什么;会有几个到多个,连接到不同的数据库,但都具有相同的模式。所以不能在应用内部的persistence.xml中指定数据源名称;它必须来自外部(很可能是配置文件)。

我认为我不能注入 EntityManagerFactory 或 EntityManager;它们与persistence.xml 中的配置紧密耦合,我似乎无法覆盖JTA 数据源名称。例如,这不起作用

@PersistenceUnit(unitName="myPU")
private EntityManagerFactory emf;
// ...
    Map<String, Object> emProps = new HashMap<String, Object>();
    emProps.put(EntityManagerProperties.JTA_DATASOURCE, "jdbc/foobar");
    EntityManager em = emf.createEntityManager(emProps);

这里我作为我的EntityManager仍然连接到在persistence.xml中实际指定的JTA数据源。

所以我开始考虑通过非注入方式创建 EntityMangerFactory,例如使用Persistence.createEntityManagerFactory(puName, propMap),但在这里,无论persistence.xml 我的属性映射说什么,我都得到了一个RESOURCE_LOCALEntityManagerFactory!

如何获得启用了 JTA并且与编译时未知的任意数据源名称相关联的 EntityManager 或 EntityManagerFactory?

【问题讨论】:

  • 资源点和容器中的 JNDI 查找,您可以定义应用程序所需的名称,然后将它们连接到实际资源。这允许您定义持久性单元以查找特定名称的数据源,然后将其绑定到实际数据源。如果没有将容器管理的持久性单元配置为使用容器管理的资源,如数据源和事务控制器,则不能拥有容器管理的持久性单元。容器需要预先知道它们,才能正确管理所有内容。
  • 我不需要它成为容器管理的持久性单元。我想要一个支持 JTA 的 EntityManager。你是说只有在容器管理的情况下才能拥有 JTA?
  • 不,但是您如何将您的事务与您的数据源相关联?这一切通常由容器通过在部署期间关联数据源来无缝处理。如果您展示了如何在运行时创建/获取数据源,我相信有人可以帮助您将其注入持久性单元(EclipseLink 有许多可以使用的属性和侦听器),但此时,您要问的是似乎很开放。
  • 在您上面使用的代码中,容器正在注入 EMF,其中已经定义了数据源和属性。您需要创建自己的 EMF 并传入数据源属性。
  • 是的,我的问题 - 我可以尝试在上面更清楚地说明这一点 - 是当我创建自己的 EMF 时,即使我在属性中指定 JTA,它也始终是 RESOURCE_LOCAL。我知道注入提供了 JTA 连接,但我们已经建立了注入并不是特别动态的。 可以创建 JTA EMF 吗?

标签: jpa weblogic eclipselink jta


【解决方案1】:

这可以解决问题,至少在 EclipseLink 2.5.2 中:

    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA");
    properties.put(PersistenceUnitProperties.JTA_DATASOURCE, "jdbc/foobar");
    emf = Persistence.createEntityManagerFactory("myPU", properties);
    JpaEntityManagerFactory jemf = (JpaEntityManagerFactory)emf;

    WebLogicTransactionController wlstx = new WebLogicTransactionController();
    if (jemf.getDatabaseSession() != null && jemf.getDatabaseSession().getExternalTransactionController() == null) {
        jemf.getDatabaseSession().setExternalTransactionController(wlstx);
    }
    if (jemf.getServerSession() != null && jemf.getServerSession().getExternalTransactionController() == null) {
        jemf.getServerSession().setExternalTransactionController(wlstx);
    }

通过将事务控制器添加到 EMF,它会再次加入 JTA 并将尊重 JTA 事务。我的 persistence.xml 为 JTA 数据源提供了一个虚拟值;我在代码中覆盖,然后我们就走了!

NB:目前getDatabaseSession()getServerSession() 实际上返回完全相同的对象。我可以只设置其中一个,但这是没有记录的,你最好安全地设置它们,以确保。

【讨论】:

    猜你喜欢
    • 2015-02-10
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多