【发布时间】:2020-01-05 06:34:50
【问题描述】:
我已将 hibernate 的版本升级到 5.3.10.Final (hibernate-core) 以在 java 8 和 WildFly 17.0.1 Final 上运行。大多数应用程序运行良好,但在休眠某些操作时实体和递归循环存在一个问题。 (升级前没有这个问题)
我试图以某种方式更改实体的属性以修复此问题,但无法获得正确的版本。问题是,当没有对项目进行任何更改时,然后在某些操作(在数据库中搜索)我得到了 hibernate 的嵌套循环,这是由以下原因引起的:
Caused by: java.lang.StackOverflowError
Caused by: java.lang.StackOverflowError
at org.jboss.jca.adapters.jdbc.WrappedConnection.checkException(WrappedConnection.java:2019)
at org.jboss.jca.adapters.jdbc.WrappedStatement.checkException(WrappedStatement.java:1436)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:509)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2167)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1930)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1892)
at org.hibernate.loader.Loader.doQuery(Loader.java:937)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:310)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2281)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:64)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:54)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4273)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:511)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:481)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:222)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:119)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:92)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1257)
at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:1115)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:178)
at org.hibernate.proxy.AbstractLazyInitializer.getIdentifier(AbstractLazyInitializer.java:89)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:372)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242)
at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:61)
at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:54)
at org.hibernate.internal.AbstractSharedSessionContract.generateEntityKey(AbstractSharedSessionContract.java:524)
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:867)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:718)
at org.hibernate.loader.Loader.processResultSet(Loader.java:990)
at org.hibernate.loader.Loader.doQuery(Loader.java:948)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:310)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2281)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:64)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:54)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4273)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:511)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:481)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:222)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:119)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:92)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1257)
at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:1115)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:178)
at org.hibernate.proxy.AbstractLazyInitializer.getIdentifier(AbstractLazyInitializer.java:89)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:372)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242)
at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:61)
at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:54)
at org.hibernate.internal.AbstractSharedSessionContract.generateEntityKey(AbstractSharedSessionContract.java:524)
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:867)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:718)
at org.hibernate.loader.Loader.processResultSet(Loader.java:990)
at org.hibernate.loader.Loader.doQuery(Loader.java:948)
... (the same in loop)
我注意到第一次调用 doQueryfunction 时它显示 937 行号,而第二次调用时它在日志中显示 948 行号。
然后,当我在WorkinfoEntity 中对下面的代码进行更改以删除级联 MERGE 和 PERSIST 时,StackOverflow 的错误在搜索时不会出现在大多数实体上(它是过去的,不能让它再次以这种方式工作......)但是然后某个时候找不到实体(带有一些附件的特殊实体)出现了一些问题(但是有带有附件的工作实体)
Unable to find AttachmentEntity with id AttachmentEntityKey [workInfoAttachmentNumber=1000000351 workInfo=WorkInfoEntity@d198fb73]
(在这个项目中workInfoAttachmentNumber不是唯一的,不像attachemnt的id)
我认为问题可能与任何hashCode 或equals 函数或@EmbeddedId 类有关(我已经读过它们不应该使用但它们已经在项目中,我不确定我是否可以更改)。我试图更改注释属性(即使我会以某种方式随机说)但没有达到预期的效果。
我认为问题出在的类的代码部分:
@Entity
@Table(name = "ITEM_WORK_INFO")
public class WorkInfoEntity extends AbstractEntryEntity implements Serializable {
private static final long serialVersionUID = 7681809420366638143L;
public WorkInfoEntity() {}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ITEM_ID", nullable = false)
private AbstractItemEntity item;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "SUBMIT_DATE")
private Date submitDate;
@Lob
@Column(name = "NOTES", columnDefinition = "CLOB")
private String notes;
@Column(name = "SUMMARY", length = 4000)
private String summary;
@Column(name = "LAST_MODIFIED_BY")
private String lastModifiedBy;
@Column(name = "EMPTY_SLOTS")
private String emptySlots = "";
@OneToMany(mappedBy = "id.workInfo", cascade = {CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY)
// @Fetch(FetchMode.JOIN)
private Set<AttachmentEntity> workinfoAttachments = new HashSet<AttachmentEntity>();
... // setters and getters
@Override
public int hashCode() {
final int prime = 31;
int result = 23;
result = (prime * result) + ((emptySlots == null) ? 0 : emptySlots.hashCode());
result = (prime * result) + ((lastModifiedBy == null) ? 0 : lastModifiedBy.hashCode());
result = (prime * result) + ((submitDate == null) ? 0 : submitDate.hashCode());
result = (prime * result) + ((summary == null) ? 0 : summary.hashCode());
result = (prime * result) + ((workinfoAttachments == null) ? 0 : workinfoAttachments.hashCode());
result = (prime * result) + ((notes == null) ? 0 : notes.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final WorkInfoEntity other = (WorkInfoEntity) obj;
if (this.submitDate != other.submitDate && (this.submitDate == null || !this.submitDate.equals(other.submitDate))) {
return false;
}
if ((this.notes == null) ? (other.notes != null) : !this.notes.equals(other.notes)) {
return false;
}
if ((this.summary == null) ? (other.summary != null) : !this.summary.equals(other.summary)) {
return false;
}
if ((this.lastModifiedBy == null) ? (other.lastModifiedBy != null) : !this.lastModifiedBy.equals(other.lastModifiedBy)) {
return false;
}
if ((this.emptySlots == null) ? (other.emptySlots != null) : !this.emptySlots.equals(other.emptySlots)) {
return false;
}
if (this.workinfoAttachments != other.workinfoAttachments && (this.workinfoAttachments == null || !this.workinfoAttachments.equals(other.workinfoAttachments))) {
return false;
}
return true;
}
@Entity
@Table(name = "WORK_INFO_ATTACHMENT")
public class AttachmentEntity implements Serializable, IEntity<AttachmentEntityKey> {
private static final long serialVersionUID = 6571993598130579018L;
@EmbeddedId
AttachmentEntityKey id = new AttachmentEntityKey();
@Column(name = "FILE_NAME")
private String fileName;
@Column(name = "FILE_SIZE")
private String fileSize;
public AttachmentEntity() {}
... // getters and setters
@Override
public AttachmentEntityKey getId() {
return id;
}
}
@Embeddable
public class AttachmentEntityKey implements Serializable {
private static final long serialVersionUID = 2354257422144993554L;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "WORK_INFO_ID", nullable = false)
private WorkInfoEntity workInfo;
@Column(name = "WORK_INFO_ATTACHMENT_NO")
private Integer workInfoAttachmentNumber;
... // getters and setters
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AttachmentEntityKey)) return false;
AttachmentEntityKey that = (AttachmentEntityKey) o;
return getWorkInfo() == that.getWorkInfo();
}
@Override
public int hashCode() {
int result = 19;
result = (31 * result) + ((getWorkInfo() != null) ? getWorkInfo().hashCode() : 0);
return result;
}
}
equals 和 hashCode 方法是我在升级后添加到 AttachmentEntityKey 的,因为我收到有关升级后未在此类中实现这些方法的警告。 (据说是复合id类)
我已经使用它几天了,找不到解决方案,所以真的很烦人。为了让这个项目充分发挥作用,您认为有什么需要改变的吗?
更新
当我删除字段workinfoAttachments feom 类及其所有用法时,项目编译并且一切工作正常。所以我可以假设这是我的问题,但我不知道如何正确解决它。
【问题讨论】:
-
我现在也遇到了同样的问题。当集合实体具有 @EmbeddedId 时,这似乎会发生
-
@RenanBaggio 我尝试删除此密钥但没有成功(它与项目结构有很大关系)。 StackOverflowError(saem 堆栈跟踪)是否存在完全相同的问题,并且您使用相同版本的 hibernate?
-
是的,我使用的是相同的版本,5.3.10.Final。但似乎这也发生在其他版本中。奇怪的是,我在使用 Hibernate 注释而不是 JPA 和 Session 注释而不是 EntityManager 时从未遇到过这个问题。
-
@RenanBaggio 如果您发现任何有用的东西,请写信,因为现在我正在尝试更改注释中的一些属性但没有成功...
-
你在使用什么 -Xss 标志?