当使用@Valid
注释与@OneToMany
关系时,我在尝试更新实体时会收到org.apache.openjpa.persistence.InvalidStateException: Detected reentrant flush.
个异常。没有@Valid
注释,更新工作正常。
为什么@Valid
注释会导致异常?
@Entity
@Table(name = "code")
public class Code {
@Valid // <-- THE PROBLEM
@OneToMany(mappedBy = "code", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<File> files;
// ...
}
@Entity
@Table(name = "file")
public class File {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Min(value = 0)
@Column(name = "id")
private long id;
@ManyToOne
@JoinColumn(name = "code_id")
private Code code;
// ...
@Override
public int hashCode() {
return (int) id;
}
}
异常发生在:
entityManager.getTransaction().commit();
完整的例外:
<openjpa-2.2.2-r422266:1468616 fatal user error> org.apache.openjpa.persistence.InvalidStateException: Detected reentrant flush. Make sure your flush-time instance callback methods or event listeners do not invoke any operations that require the in-progress flush to complete.
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2078)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1853)
at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:596)
at org.apache.openjpa.kernel.StateManagerImpl.assignField(StateManagerImpl.java:683)
at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1655)
at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1586)
at entities.File.pcGetid(File.java)
at entities.File.hashCode(File.java:144)
at org.hibernate.validator.internal.engine.ValidationContext$BeanAndPath.hashCode(ValidationContext.java:610)
at java.util.HashMap.hash(HashMap.java:366)
at java.util.HashMap.getEntry(HashMap.java:466)
at java.util.HashMap.get(HashMap.java:421)
at org.hibernate.validator.internal.engine.ValidationContext.hasMetaConstraintBeenProcessed(ValidationContext.java:336)
at org.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1281)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:475)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:424)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:388)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:340)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraint(ValidatorImpl.java:635)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:524)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:349)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:158)
at org.apache.openjpa.lib.util.J2DoPrivHelper$61.run(J2DoPrivHelper.java:1254)
at org.apache.openjpa.lib.util.J2DoPrivHelper$61.run(J2DoPrivHelper.java:1252)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.openjpa.persistence.validation.ValidatorImpl.validate(ValidatorImpl.java:278)
at org.apache.openjpa.validation.ValidatingLifecycleEventManager.fireEvent(ValidatingLifecycleEventManager.java:123)
at org.apache.openjpa.kernel.BrokerImpl.fireLifecycleEvent(BrokerImpl.java:810)
at org.apache.openjpa.kernel.StateManagerImpl.fireLifecycleEvent(StateManagerImpl.java:419)
at org.apache.openjpa.kernel.StateManagerImpl.preFlush(StateManagerImpl.java:3007)
at org.apache.openjpa.kernel.PDirtyState.beforeFlush(PDirtyState.java:39)
at org.apache.openjpa.kernel.StateManagerImpl.beforeFlush(StateManagerImpl.java:1034)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2122)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2082)
at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2000)
at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1524)
at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:933)
at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:570)
at entities.CodePersistenceTest.updateCode(CodePersistenceTest.java:768)
我正在使用OpenJPA 2.2.2和Hibernate Validator 5.0.2
答案 0 :(得分:1)
您正在引用File#hashCode()
中的对象ID并使用生成类型IDENTITY
,它将从数据库中的标识列获取id值,即需要访问DB获得ids。显然,您的实体的检测方式会在读取id属性时导致刷新发生。
您可以尝试更改hashCode()
实施,其方式不是基于主键,而是基于&#34;商业标识&#34;该实体,例如文件名或路径。
那就是说,我认为Hibernate Validator在这种情况下不应该调用实体的hashCode()
方法,所以我已经提交了HV-848来改变它。