有一个简单的 Entry
实体。。。
@Data
@NoArgsConstructor
@Entity
public class Entry {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private Double a;
@Column
private Double b;
}
... 和一个 Container
与条目有@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);
}
}
我可以使用以下事务方法从容器中删除条目。
@Transactional
public void deleteFromContainer(Long id, Predicate<Entry> predicate) {
Container container = containerRepository.findById(id).orElseThrow(IllegalStateException::new);
Set<Entry> toBeDeleted = container.getEntries().stream()
.filter(predicate)
.collect(Collectors.toSet());
toBeDeleted.forEach(entry -> container.removeEntry(entry));
entryRepository.deleteAll(toBeDeleted);
if (container.getEntries().isEmpty()) {
containerRepository.delete(container);
}
}
一切都很好,直到我改变主意 Entry
实体。通过添加一个 transient 字段和一个为其赋值的@postload方法,删除就不可能了。
@Transient
private Double[] fields;
@PrePersist
@PreUpdate
public void setMappedFields() {
a = fields[0];
b = fields[1];
}
@PostLoad
public void setTransientFields() {
fields = new Double[]{a, b};
}
实际上 Container
类在内部存储的条目集中找不到匹配的条目。因此,这些条目在被删除之前不会从manytomy关系中删除 entryRepository.deleteAll(toBeDeleted);
将出现以下错误:
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]
尽管我和调试器检查了要删除的值在集合中是否可用。
添加了另一个函数来调试行为。只是得到一个具体的答案 Container
从数据库中删除第一个 Entry
在里面。
@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();
}
原来,同一个对象示例有时返回两个不同的hashcode()值。这样我就可以将同一个示例添加到 Set
.
我粘贴了一张图片来显示这个。显示同一示例的调试结果可以添加两次到 Set
.
有人对此有什么提示吗?谢谢你的帮助。
1条答案
按热度按时间zpf6vheq1#
您知道基于哈希的集合中的哪些条件元素与要添加/删除的元素相匹配吗?基于hashcode和equals方法。您并没有展示如何实现equals/hashcode,但我猜您只是在使用lombok生成的内容,这可能不是您想要的。默认情况下,lombok为
@Data
基于类的整个状态的带注解类、equals和hashcode方法。这是一个非常常见的初学者错误,你会发现关于这个主题的文章吨。我建议您避免同时使用lombok,自己实现equals/hashcode,这样您就知道会发生什么。