【问题标题】:Custom query within JPA server-managed sessionJPA 服务器管理会话中的自定义查询
【发布时间】:2015-05-17 21:53:51
【问题描述】:

我正在尝试在 JTA 会话(服务器管理)中执行 不相关 查询(other_table),以便在使用 JPA 将 bean EJB 持久化到 DB 之前进行一些验证。 p>

这是我想做的(大约):

@PersistenceUnit(unitName="DynamicDatabase")
EntityManagerFactory emf;

@TransactionAttribute(TransactionAttributeType.REQUIRED)
private long nextEntryid() {
    em = emf.createEntityManager();
    Query query = em.createQuery("select t from OTHER_TABLE t");
    // do some validation and checking
    MyTable bean = new MyTable();
    em.persist(bean);
}

但是我不断收到服务器错误,它不允许与其他未持久化的数据库项进行交互:

org.apache.openjpa.persistence.ArgumentException:
An error occurred while parsing the query filter (query): The name "OTHER_TABLE" is not a recognized entity (...) Perhaps you meant MyTable, which is a close match.

<persistence-unit name="DynamicDatabase" transaction-type="JTA">
    <jta-data-source>jdbc/DB2DynamicConnection</jta-data-source>
    <class>jorge.java.dynamicdatabase.db.MyTable</class>
    </properties>
</persistence-unit>

问题是:在同一个 JPA DB 连接和 JTA 事务中查询/更改另一个表的正确方法是什么?

对此我很陌生,请耐心等待。在这方面工作了很长时间。

编辑:我认为这无关,但仅供参考,我正在使用 WebSphere Liberty Profile 8.5.5.4、JSDK 8u31、EclipseEE Luna 4.4.2 for Web Dev .将其添加到标签中。

【问题讨论】:

    标签: jdbc jta websphere-liberty jpa-2.1 jdk6


    【解决方案1】:

    问题是您有一个引用实体OTHER_TABLE 的@NamedQuery,并且它不存在或未标记为实体(在Java 类和persistence.xml 中尝试)。

    如果OtherTable Java 类不是实体并且它必须保持不变,那么您可以使用Constructors in JPQL-queries

    SELECT NEW com.domain.reports.MyReport(u.firstName, u.lastName, u.birthday) FROM User u
    

    如果您需要编写普通的 SQL 查询,那么您可以使用 native queries 来完成,因为它们在 JPA 规范中是已知的。

    【讨论】:

    • 对不起,但这就是重点——我想直接查询其他不(或不能)由 Java 持久性管理的东西,并且查询必须在同一个数据库事务中运行。
    • 你的回答给了我一个想法,再深入一点我猜想函数“javax.persistence.EntityManager.createQuery(String)”显然需要一个Entity,也就是说,它不能用对于其他不同的东西。一旦我的代码工作,我会发布我的答案。
    • 如果你真的了解实体是什么,如果你确定OTHER_TABLE不是实体,那么你可以看看Constructors in JPQL-queries
    • 这是一个非常有趣的答案,我的朋友,哇,我会给它+1,因为很多人肯定会使用它。但是,对于最终解决方案,我希望对“无关查询”更加通用/通用。我的真实示例要复杂得多,我无法从任何 Java 对象等中处理它。
    • 由于我的真实查询不同(与序列等有关),所以我选择了 Native Query 解决方案,效果很好!
    【解决方案2】:

    根据 Andrei 的建议,JPQL(Java 持久性查询语言)对对象而不是表进行操作。这意味着em.createQuery() 不能用于通用数据库交互。

    一般来说,执行任何 SQL 语句(在容器管理的事务 JTA 内部),都需要从实体管理器获取 DB 连接(它将返回持久性上下文单元 JPA)。

        // Get container's objects
        em = emf.createEntityManager();
        java.sql.Connection conn = em.unwrap(java.sql.Connection.class);
    
        // Run the query
        Statement sql = conn.createStatement();
        ResultSet rs = sql.executeQuery("select * from OTHER_TABLE");
        rs.next()
        (...)
    
        //Container-managed connection shouldn't be closed. 
        rs.close;
        sql.close;
    

    请注意,unwrap 调用适用于 JPA,但不适用于 Hibernate(在这一点上已经存在其他问题)。请注意用于 SQL 语句 select * from 的语言与用于命名查询 JPQL select t from 的语言不同。异常处理也必须像往常一样使用} finally { 子句进行控制。

    这样可以在不使用 JAVA 实体的情况下在服务器管理的事务中执行复杂的自定义语句,我终于可以睡觉了。

    【讨论】:

    • 有一个下注的解决方案然后这个:native queries
    • 您好@AndreiI,您能否将该评论作为答案发送,以便我将其标记为解决方案(绿色复选)?
    • 我已将带有“本机查询”的部分添加到我的答案中。
    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2015-12-20
    相关资源
    最近更新 更多