java - 每次在 Hibernate 中动态创建 EntityManager/连接到自定义主机/DB

标签 java hibernate entitymanager websphere-liberty

我有一个在 Websphere Liberty 上运行的应用程序,它应该比较来自 2 个数据库/模式的表。

用户应该能够输入连接数据,例如主机和凭据。

我正在使用 Hibernate 访问应用程序数据库。

我尝试使用多个持久性单元,一个用于应用程序数据库,一个用于所有其他数据库。

但是我有两个问题:

  1. 我收到“非法尝试征用多个 1PC XAResources” 有时会出错
  2. 可以查询 2 个数据库 用户提交的凭据,但除非连接,否则我没有得到任何结果 到 server.xml 文件中列出的与数据源相同的数据库

这是服务器上server.xml上的数据源(dbs是oracle dbs)

<dataSource id="MyAppDS" jndiName="jdbc/MyDS" type="javax.sql.ConnectionPoolDataSource">
    <jdbcDriver javax.sql.ConnectionPoolDataSource="oracle.jdbc.pool.OracleConnectionPoolDataSource" libraryRef="OracleSQLLib"/>
    <connectionManager agedTimeout="30m" connectionTimeout="10s" maxPoolSize="20" minPoolSize="5"/>
    <properties password="..." url="jdbc:oracle:thin:@...:1521:..." user="..."/>
</dataSource>
<dataSource id="OtherOracle" jndiName="jdbc/OtherOracle" type="javax.sql.ConnectionPoolDataSource">
    <jdbcDriver javax.sql.ConnectionPoolDataSource="oracle.jdbc.pool.OracleConnectionPoolDataSource" libraryRef="OracleSQLLib"/>
    <connectionManager agedTimeout="30m" connectionTimeout="10s" maxPoolSize="20" minPoolSize="5"/>
    <properties password="..." url="jdbc:oracle:thin:@127.0.0.1:1521:XE" user="..."/>
</dataSource>

这是 EJB 模块上的 persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="main-persistence">
    <jta-data-source>jdbc/MyDS</jta-data-source>

    <class>classes...</class>

    <properties>
        <property name="hibernate.transaction.jta.platform"
            value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" />
        <property name="hibernate.dialect"
            value="org.hibernate.dialect.Oracle9iDialect" />
        <property name="hibernate.temp.use_jdbc_metadata_defaults"
            value="false" />
    </properties>
</persistence-unit>
<persistence-unit name="other-persistence" transaction-type="RESOURCE_LOCAL">
    <non-jta-data-source>jdbc/OtherOracle</non-jta-data-source>
    <class>classes...</class>

    <properties>
        <property name="hibernate.transaction.jta.platform"
            value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" />
        <property name="hibernate.dialect"
            value="org.hibernate.dialect.Oracle9iDialect" />
        <property name="hibernate.temp.use_jdbc_metadata_defaults"
            value="false" />
    </properties>
</persistence-unit>

在 Java Bean 上我使用 EntityManagerFactory

    @PersistenceUnit(unitName = "other-persistence")
    private EntityManagerFactory emf;

我使用这样的自定义凭据创建实体管理器

    Map<String, String> properties = new HashMap<String, String>();
    properties.put("hibernate.connection.driver_class", "oracle.jdbc.OracleDriver");
    properties.put("hibernate.connection.url", myCustomCreatedConnectionUrl);
    properties.put("hibernate.connection.username", customUser);
    properties.put("hibernate.connection.password", customPassword);
    properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle9iDialect");
    properties.put("hibernate.show-sql", "true");
    EntityManager entityManager = emf.createEntityManager(properties);

如果我使用 getProperties 检查 EntityManager 属性,一切似乎都是正确的。但仅当凭据/主机 = 数据源时,查询才有效。否则我不会得到任何结果(但没有错误)

问题可能是什么? 有没有一种方法可以只使用一个持久性单元,但使用自定义主机/凭据来执行不同的查询?

最佳答案

关于第一个错误“非法尝试登记多个 1PC XAResources”,出现这种情况是因为您在同一事务中使用这两种资源。我可以在您的配置中看到 <non-jta-data-source>jdbc/OtherOracle</non-jta-data-source>,这表明您可能打算jdbc/OtherOracle 成为非登记资源。要使其工作,数据源本身需要配置为非登记。您可以使用 transactional="false" 属性来执行此操作,如下所示:

<dataSource id="OtherOracle" jndiName="jdbc/OtherOracle" type="javax.sql.ConnectionPoolDataSource" transactional="false">
...

另一方面,如果您确实希望这两个资源都参与事务,那么您需要使用 XADataSource 而不是 ConnectionPoolDataSource。以下是如何执行此操作的示例(请注意,必须为此更新 type 下的类型 dataSource jdbcDriver 下的属性和类:

<dataSource id="MyAppDS" jndiName="jdbc/MyDS" type="javax.sql.XADataSource">
    <jdbcDriver javax.sql.XADataSource="oracle.jdbc.xa.client.OracleXADataSource" libraryRef="OracleSQLLib"/>
    <connectionManager agedTimeout="30m" connectionTimeout="10s" maxPoolSize="20" minPoolSize="5"/>
    <properties password="..." url="jdbc:oracle:thin:@...:1521:..." user="..."/>
</dataSource>
<dataSource id="OtherOracle" jndiName="jdbc/OtherOracle" type="javax.sql.XADataSource">
    <jdbcDriver javax.sql.XADataSource="oracle.jdbc.xa.client.OracleXADataSource" libraryRef="OracleSQLLib"/>
    <connectionManager agedTimeout="30m" connectionTimeout="10s" maxPoolSize="20" minPoolSize="5"/>
    <properties password="..." url="jdbc:oracle:thin:@127.0.0.1:1521:XE" user="..."/>
</dataSource>

在第二个问题中,我认为您是说不同的用户无法看到数据。这可能是因为不同的数据库用户使用不同的架构并且无法访问彼此的数据吗?如果您可以使用通用架构获取所有用户,则添加 @Table(schema="YOUR_SCHEMA_NAME")至 JPA @Entity可能有帮助。 Table 注释的 JavaDoc 可以找到 here .

关于java - 每次在 Hibernate 中动态创建 EntityManager/连接到自定义主机/DB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59948188/

相关文章:

java - Hibernate - 删除对象

java - 从另一个类调用 JFrame 来更改 JPanel

java - 如何在android中的可扩展 ListView 组和 subview 中加载json数据?

Java:如何从文本文件中仅读取int数据来执行计算?

doctrine-orm - 如何在 Doctrine 中附加分离的实体?

java - EntityManager.getResultList() 性能缓慢

java - 在 Java 方法的参数中使用 printf

java - 在 Spring 类中获取 Hibernate 事务

hibernate - Spring MVC、Hibernate 3 和@Valid 问题

java - 如何在 JPA 中接受 Map<String,Object> 类型的元组