我正在尝试在JTA会话(服务器管理的)中执行不相关的查询(other_table),以便在使用JPA将bean EJB持久化到DB之前进行一些验证。
这是我想做的事(aprox):
@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 。要将其添加到标签。
答案 0 :(得分: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规范中已知。
答案 1 :(得分:0)
根据Andrei的建议,JPQL(Java持久性查询语言)在对象上运行,而不是在表上运行。这意味着em.createQuery()
无法用于通用数据库交互。
一般来说,要执行任何SQL语句(在容器管理的事务JTA中),必须从实体管理器获取数据库连接(它将返回持久化上下文单元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实体,我终于可以睡觉了。