有一个实体'地址'和另一个实体'建筑物' 在一个地址可以有多个建筑物。
在building.java上我的地址定义为:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ADDRESS_ID_REF")
public Address getAddress() {
return this.address;
}
地址构建定义为:
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "address")
public Set<Building> getBuildings() {
return this.buildings;
}
试图做的时候
em.remove(building)
它确实有用
坏情况的构造与好的情况完全相同,再加上参考同一地址将第二个建筑物插入数据库。
在坏的情况下(hibernate没有做任何删除)我仍然可以删除数据库中的行(delete from building where building_id = '123'
)。没有关于引用的SQL错误。
在类似的线程中,我读到在这种情况下通常会留下引用,使得hibernate正确无法删除此实体。
不幸的是,我也没有得到任何hibernate的log4j输出,也没有异常发生。所以我不知道hibernate在这个地方的问题是什么。
我的log4j.properties适用于我的记录器。输出按预期写入控制台。 但我没有得到任何Hibernate日志记录。 我在另一个帖子中读到这个记录器应该给我一些提示: org.hibernate.event.internal.DefaultPersistEventListener
log4j.rootLogger=TRACE, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.category.com.myproject.mypackage=INFO
log4j.category.com.myproject.mypackage.myclass=DEBUG
log4j.category.org.hibernate.event.internal.DefaultPersistEventListener=TRACE
log4j.category.org.hibernate=TRACE
log4j.category.org.springframework=TRACE
当在persistence.xml show_sql中设置为true时,我将把SQL写入控制台。在那里我可以看到没有执行删除sql。但我没有看到任何错误。
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
在大多数情况下写在其他线程中似乎有一些必须首先删除的引用。 但在我的情况下,我的实体是子对象,这意味着我不希望外国人建立指导解决问题。 另外,我可以通过SqlDeveloper直接删除构建行。 从
更改代码时em.remove(building)
到
em.remove(address)
由于级联,所有三个实体都被删除。但这不是我想要的,我只想删除单个建筑物。 我想要得到它,我需要看到缺少的hibernate loggings(希望有一些)。
如果您需要更多信息,请索取。 提前谢谢。
答案 0 :(得分:1)
(这将是一个评论,但我没有足够的声誉)你想要实现什么或更好的什么不起作用?删除建筑物不应删除地址,因为@ManyToOne注释中没有级联选项。如果你试图删除建筑物从建筑物集中删除它,你需要在@OneToMany注释中使用orphanRemoval = true
编辑(阅读评论后)
最简单的方法是: 将orphanRemoval = true添加到@OneToMany地址映射。比
Building b .... // current Object to be deleted
b.getAddress().getBuildings().remove(b);
b.setAddress(null);
em.merge(a);
这段代码
b.getAddress().getBuildings().remove(b);
b.setAddress(null);
您可以在地址实体中创建单独的方法,例如
public void removeBuilding(Building b){
buildings.remove(b);
b.setAddress(null);
}
答案 1 :(得分:0)
我不确定框架是否正确和有意,但我找到了解决方案/解决方法:
而不是只做:
em.remove(b);
我现在在做:
Building b .... // current Object to be deleted
Address a = b.getAddress();
Set<Building> bSet = a.getBuildings();
bSet.remove(b);
em.remove(b);
这很好用。 希望这是有效的。
解释可能是: 即使事务方法结束,删除子实体也不会更新子项的父列表(意味着提交已完成)。
我原本以为在删除子实体并进行提交时,会从数据库中删除该实体。 然后,当在新的事务中加载aparent实体时,其所有子权限都从数据库中进行后退,因此在父端不再列出已删除的子实体。 也许(虽然是事务执行)一些数据保存在缓存中?
正如在另一条评论中所说,只是在地址实体中添加orphanRemoval = true给cascadeAll-Line不会产生任何影响。