Java Spring JPA:@PostLoad方法中对瞬态字段的赋值中断了从多个关系中删除实体

Java Spring JPA:@PostLoad方法中对瞬态字段的赋值中断了从多个关系中删除实体,java,spring-boot,hibernate,spring-data-jpa,Java,Spring Boot,Hibernate,Spring Data Jpa,有一个简单的条目实体 @Data @NoArgsConstructor @Entity public class Entry { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column private Double a; @Column private Double b; } 。。。以及一个容器实体,它与条目保持@manytomy关系

有一个简单的
条目
实体

@Data
@NoArgsConstructor
@Entity
public class Entry {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private Double a;

    @Column
    private Double b;
}
。。。以及一个
容器
实体,它与条目保持@manytomy关系

@Data
@Entity
public class Container {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long container_id;

    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Entry> entries;

    public Container() {
        entries = new HashSet<>();
    }

    public void removeEntry(Entry e) {
        entries.remove(e);
    }

    public void add(Entry e) {
        entries.add(e);
    }
}
实际上,
容器
类中的removentry()方法在内部存储的条目集中找不到匹配的条目。因此,这些条目在被删除之前不会从多个关系中删除

entryRepository.deleteAll(待删除)

将出现以下错误:

DEBUG 12744 --- [  restartedMain] org.hibernate.SQL                        : delete from entry where id=?
TRACE 12744 --- [  restartedMain] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [2]
WARN  12744 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 23503, SQLState: 23503
ERROR 12744 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : Referential integrity constraint violation: "FKGWCV239MEJWTTQTY8LBBOYRYO: PUBLIC.CONTAINER_ENTRIES FOREIGN KEY(ENTRIES_ID) REFERENCES PUBLIC.ENTRY(ID) (2)"
    Referential integrity constraint violation: "FKGWCV239MEJWTTQTY8LBBOYRYO: PUBLIC.CONTAINER_ENTRIES FOREIGN KEY(ENTRIES_ID) REFERENCES PUBLIC.ENTRY(ID) (2)"; SQL statement:
    delete from entry where id=? [23503-200]
尽管我使用调试器检查了要删除的值在集合中是否可用

添加了另一个函数来调试该行为。只需从数据库中获取特定的
容器
,并尝试删除其中的第一个
条目

    @Transactional
    public void deleteFirstEntryFromContainer(Long id) {
        Container container = containerRepository.findById(id).orElseThrow(IllegalStateException::new);

        Set<Entry> entries = container.getEntries();

        Entry entryToBeDeleted = entries.stream().findFirst().orElseThrow(IllegalStateException::new);

        int sizeBefore = entries.size();
        boolean contains = entries.contains(entryToBeDeleted);

        entries.add(entryToBeDeleted);
        int sizeAfter = entries.size();

        HashSet<Entry> newSet = new HashSet<>(entries);
        int sizeOfNew = newSet.size();
    }
@Transactional
public void deleteFirstEntryFromContainer(长id){
Container Container=containerRepository.findById(id).orelsetrow(IllegalStateException::new);
Set entries=container.getEntries();
Entry entryToBeDeleted=entries.stream().findFirst().OrelsThrow(IllegalStateException::new);
int-sizeBefore=entries.size();
boolean contains=entries.contains(entryToBeDeleted);
条目。添加(条目被删除);
int sizeAfter=entries.size();
HashSet newSet=新的HashSet(条目);
int-sizeOfNew=newSet.size();
}
事实证明,同一个对象实例有时返回两个不同的hashCode()值。这样我就可以将同一个实例两次添加到
集合

我粘贴了一张显示这个的图片。

有人对此有什么暗示吗?
谢谢您的帮助。

您知道基于哈希的集合中的哪些条件元素与要添加/删除的元素相匹配吗?基于hashCode和equals方法。您没有展示如何实现equals/hashCode,但我猜您只是在使用Lombok生成的内容,这可能不是您想要的。默认情况下,Lombok为
@Data
注释类生成基于类的整个状态的equals和hashCode方法。这是一个非常常见的初学者错误,你会发现很多关于这个主题的文章。
我建议您避免同时使用Lombok,自己实现equals/hashCode,这样您就知道会发生什么。

是的,您是对的。我在这里使用从Lombok生成的hashCode()和equals()方法。当我将这些减少到只考虑id字段时,它就可以正常工作了。但我需要在这些方法中使用所有字段。最有可能的是,在问题的第一个版本中,我的发现不够清楚,因此我更新了更多信息。关于使用Hibernate和Lombok的常见陷阱的有用视频:删除
@Data
注释可以解决问题,即使没有实现专用的equals/hashCode()方法,因此,使用
对象
类中的默认java实现@zforgo,谢谢你的视频链接。另一个有趣的例子是“使用Hibernate和JPA实现Equals和HashCode的终极指南”:
DEBUG 12744 --- [  restartedMain] org.hibernate.SQL                        : delete from entry where id=?
TRACE 12744 --- [  restartedMain] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [2]
WARN  12744 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 23503, SQLState: 23503
ERROR 12744 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : Referential integrity constraint violation: "FKGWCV239MEJWTTQTY8LBBOYRYO: PUBLIC.CONTAINER_ENTRIES FOREIGN KEY(ENTRIES_ID) REFERENCES PUBLIC.ENTRY(ID) (2)"
    Referential integrity constraint violation: "FKGWCV239MEJWTTQTY8LBBOYRYO: PUBLIC.CONTAINER_ENTRIES FOREIGN KEY(ENTRIES_ID) REFERENCES PUBLIC.ENTRY(ID) (2)"; SQL statement:
    delete from entry where id=? [23503-200]
    @Transactional
    public void deleteFirstEntryFromContainer(Long id) {
        Container container = containerRepository.findById(id).orElseThrow(IllegalStateException::new);

        Set<Entry> entries = container.getEntries();

        Entry entryToBeDeleted = entries.stream().findFirst().orElseThrow(IllegalStateException::new);

        int sizeBefore = entries.size();
        boolean contains = entries.contains(entryToBeDeleted);

        entries.add(entryToBeDeleted);
        int sizeAfter = entries.size();

        HashSet<Entry> newSet = new HashSet<>(entries);
        int sizeOfNew = newSet.size();
    }