尝试使用EntityManager创建NativeQuery时出现IllegalStateException

时间:2016-08-12 17:17:02

标签: mysql java-ee eclipselink

尝试使用我的实体管理器创建本机查询时,我遇到了这个恼人的异常。完整的错误消息是:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.model.OneToManyEntity2@61f3b3b.
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:313)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:723)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:441)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:874)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:967)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:207)
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:521)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400)

触发错误的实际代码是:

    Query query;
    query = entityManager.createNativeQuery(
            "SELECT MAX(CAST(SUBSTRING_INDEX(RecordID,'-',-1) as Decimal)) FROM `QueriedEntityTable`");
    String recordID = (query.getSingleResult() == null ?
            null :
            query.getSingleResult()
                 .toString());

这是在doTransaction部分中使用EntityTransaction执行的。让我了解这一点的部分是,这是在doTransaction方法中执行的第一个代码,简化如下:

updateOneToManyEntity1();
updateOneToManyEntity2();
entityManager.merge(parentEntity);

它与#34; OneToManyEntity1"有问题的实体甚至不是我试图创建查询的表格。在此之前,我没有做任何坚持或合并,所以我也不确定是什么导致它不同步。在执行此代码之前,唯一正在完成的数据库工作只是提取数据,而不是更改任何内容。外键已在数据库中正确设置。

我能够通过按照说法执行并将这些关系标记为Cascade.PERSIST来摆脱此错误,但后来我在query.getSingleResult()行上得到了一个MySQLContrainstraViolationException。我的日志显示它在此之前做了一些INSERT查询,所以看起来它到达了我的doTransaction方法的EntityManager.merge部分,但错误和调用堆栈指向代码的完全不同的部分。

使用EclipseLink(2.6.1),Glassfish 4和MySQL。 entitymanager正在使用RESOURCE_LOCAL,其中包含persistence-unit标记下列出的所有必需类,exclude-unlisted-classes设置为false。

编辑:更多信息,因为我试图解决这个问题。如果我在事务开始时放置一个断点,然后通过IntelliJ"评估表达式"执行entityManager.clear();工具,至少在第一次通过时一切正常。没有它,我会在尝试将空对象插入表中时收到错误。

编辑#2:我将nativeQuery部分转换为使用Criteria API,这让我实际通过我的代码,所以我可以找到无意中将null对象添加到我的实体列表的位置。我仍然只是混淆了为什么实体管理器缓存这些错误或某些东西,以至于创建本机查询正在破坏,因为它仍在尝试插入错误的数据。这是我在每次做之前需要调用EntityManager.clear()的东西吗?或者我应该在doTransaction方法中出现错误时调用它?

1 个答案:

答案 0 :(得分:0)

因此,在重新编写代码并将其放在一边之后,我偶然发现了至少部分问题的答案。我的问题是由于事务在事务开始之前被持久化引起的。因此,当我输入我的事务时,它首先尝试从我的实体对象插入/更新数据并抛出错误,因为我没有设置大多数非空列的值。我相信这是我得到级联错误的原因,我很肯定这是我看到在我的交易开始时被解雇的随机插入查询的来源。希望这可以帮助别人避免很多麻烦。