java - 一对多 JPA 注释不会删除孤儿

标签 java unit-testing hibernate orm jpa

我正在尝试构建一个用户和联系人管理项目。 我有很多类(class),因此将其限制为此处关注的内容。我有一个 userAccount、userProfile 和组 这是用户帐户映射

@Id @GeneratedValue
@Column(name="USER_ACCOUNT_ID")
private Long ID; 
 ......
 @Column(name="EMAIL", length=100, unique=true)
private String email;

@OneToOne(targetEntity=UserProfileImpl.class,cascade={CascadeType.ALL})
 @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@JoinColumn(name="USER_PROFILE_ID")
private UserProfile profile;

 @OneToMany(targetEntity=GroupImpl.class, cascade={CascadeType.ALL})
 //    @JoinColumn(name="USER_ACCOUNT_ID")
@JoinTable(name = "USER_ACCOUNT_CONTACT_GROUP", joinColumns = @JoinColumn(name = "USER_ACCOUNT_ID"), inverseJoinColumns = @JoinColumn(name = "GROUP_ID"))
@org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Group> groups = new HashSet<Group>();
........

这是用户配置文件

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="USER_PROFILE_ID")
private Long ID;
.....
 @OneToOne(mappedBy="profile", targetEntity=UserAccountImpl.class)
private UserAccount userAccount;
.....

这里是群组

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="GROUP_ID")
private Long ID;    
.......
@Column(name="NAME", length=100, unique=true)
private String Name;

@ManyToOne(targetEntity=UserAccountImpl.class)
@JoinColumn(name="USER_ACCOUNT_ID",nullable=false)
private UserAccount userAccount;

所以基本上就是这样。在测试中将 userAccount 对象添加到 group.so 之前,一切都很顺利。我创建 userProfile、userAccount 和组(使用 spring @autowired)。
在 setUP (@Before) 方法中,我为 userProfile 设置了一些 prop,并将其及其 prop 添加到 useAccount 并保留它,然后将 useAccount 设置为组。
在tearDown(@After)上我删除了userACcount。
在我的 testSave 上(保存组)工作正常(对所有操作使用相同的 session ),但控制台上没有针对该组的删除 sql 查询,但它会删除 userAccount。
通过在拆卸方法中删除 userAccount,我希望组应该被删除。但事实并非如此。
更糟糕的是,由于对组名称的独特限制,其他测试都失败了。我在网上搜索,但我尝试的一切似乎都不起作用。谁能拯救我:)?我的意思是我该怎么做?感谢您的阅读

这是我根据收到的回复进行的尝试的更新。 我已将其添加到 group.setUserAccount(null) 到我的 removeGroup,现在是这个

public void removeGroup(Group group) {
    try{
       if(this.groups.contains(group)){
        group.setUserAccount(null);
        this.groups.remove(group);
       }
    } catch(Exception ex){
        ex.printStackTrace();
    }
}

因此,对于我使用的具有相同行为的测试,即删除 userAccount 但不删除组

ua1.removeGroup(g1);
uaDao.delete(ua1);

我猜它没有进入 if block ,因为我应该具有与此相同的行为:

 g1.setUserAccount(null);
 uaDao.delete(ua1);

另一个抛出错误

PropertyValueException: not-null property references a null or transient value

所以我想我会使用以下方法删除该组:

gDao.delete(g1);
uaDao.delete(ua1);

希望我能找到一种方法来解决这个问题。感谢那些帮助过我的人,特别是 Pascal,如果您有其他想法或发现我的代码有问题,我将非常乐意纠正它。谢谢阅读

最佳答案

首先,如果 UserAccount -> Group 关系是双向的,那么您需要将反向集合侧映射为

@OneToMany(targetEntity=GroupImpl.class, cascade{CascadeType.ALL},mappedBy="userAccount")

现在 Hibernate 知道 UserAccount 是集合的所有者。现在要删除,正如 @Pascal 所说,您需要解除双方的绑定(bind)。由于 Hibernate 忽略集合,因此所有者负责绑定(bind)关系,因此基本上像这样的辅助方法会在 UserAccount

中创建关联
public void addGroup(Group group){
     group.setUserAccount(this);
     groups.add(group);
}

现在删除另一个辅助方法

public void removeGroup(Group group){
    group.setUserAccount(null);
    groups.remove(group);
}

现在可以删除

UserAccount ua = //load user account object
for(Group g : ua.getGroups())
      ua.removeGroup(g);

session.delete(ua);

您的代码现在应该可以工作了。您不必按照我的方式进行操作,但我希望您能明白其中的意思。DELETE_ORPHAN 应该负责的级联删除

关于java - 一对多 JPA 注释不会删除孤儿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1735889/

相关文章:

java - 持久性模型与 View 模型

java - 线程中出现异常 "AWT-EventQueue-0"java.lang.NullPointerException 错误,该怎么办?

java - 使用什么拉解析器实现以及何时使用?

python - GeoDjango 和混合器。 'PointField'没有属性 '_meta'

javascript - 使用 $compile 编译指令后 Controller 的范围未定义

java - where 子句中参数的动态数量

java - 通过 native SQL删除的子实体仍然存在于entityManager中

java - Android单元测试onclick方法

Java:扩展类加载器在 Java 13 中从哪里获取类?

javascript - 为什么 Node.js Assert 没有 notOk() 方法?