休眠升级后出现问题-休眠中的嵌套循环(CascadeType和EmbeddedId)

时间:2019-09-02 07:55:19

标签: java hibernate jboss ejb

我已经将hibernate的版本升级到5.3.10.Final(hibernate-core)以在Java 8和WildFly 17.0.1 Final上运行。大多数应用程序都可以正常工作,但是在休眠某些操作时,实体和递归循环存在一个问题。 (升级之前没有这样的问题)

我试图以某种方式更改实体的属性以修复此问题,但无法获得正确的版本。问题是,当没有对项目进行任何更改时,然后通过某些操作(在数据库中搜索),我得到了休眠的嵌套循环,该循环是由以下原因引起的:

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)

我在那里注意到,第一次调用doQuery函数时,它将显示937行号,而第二次调用时,它将显示为948行号。 然后,当我在WorkinfoEntity中的以下代码中进行了更改以删除级联MERGE和PERSIST时,大多数实体上没有出现搜索时出现StackOverflow的错误(它是过去的,并且无法再次以这种方式工作... ),但有时会遇到一些问题,即找不到实体(特别是带有一些附件的实体)(但是有一些具有附件的工作实体)

Unable to find AttachmentEntity with id AttachmentEntityKey [workInfoAttachmentNumber=1000000351 workInfo=WorkInfoEntity@d198fb73]

(在此项目中,workInfoAttachmentNumber不是唯一的,并且不像attachemnt的ID) 我认为问题可能出在任何hashCodeequals函数或@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;
    }
}

我在升级后将equalshashCode方法添加到AttachmentEntityKey中,因为我收到有关在升级后未在此类中实现这些方法的警告。 (据说是复合id类)

我已经使用了几天,却找不到解决方案,所以这确实很烦人。您是否看到任何需要更改的内容才能尝试使该项目完全正常工作?

更新 当我删除该类及其所有用法的字段workinfoAttachments时,项目将编译,并且evrything工作正常。所以我可以保证这是我的问题,但我不知道如何正确解决。

1 个答案:

答案 0 :(得分:0)

我已经解决了该问题,因为它似乎是https://hibernate.atlassian.net/browse/HHH-13296中所述的hibernate + WildFly错误。

所以我的解决方法是删除EmbeddedId并在数据库的表中创建新的IDcolumn,这是主键2中已使用的列(EmbeddedId)的串联(并将它们设置在代码中的适当位置)