有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java onetomany JPA注释不会删除孤立项

我正在尝试建立一个用户和联系人管理项目。 我有很多课程,所以我会把它限制在这里关注的问题上。我有一个用户帐户、用户配置文件和组 下面是UserAccount映射

@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;

基本上就是这样。在a向组中添加userAccount对象之前,一切都很顺利。等等,测试。我创建userProfile、userAccount和group(使用spring@autowired)
在setUP(@Before)方法中,我将几个prop设置为userProfile,并将其与prop一起添加到usecount,并将其持久化,然后将usecount设置为组
在拆卸(@After)时,我删除了userACcount
在我的testSave上(保存组)工作正常(对所有操作使用相同的会话),但是控制台上没有针对组的deletesql查询,但是它删除了userAccount
通过删除teardown方法中的userAccount,我希望可以将组删除到。但事实并非如此
更糟糕的是,由于组名上的唯一约束,其他测试都失败了。我在网上搜索,但我尝试的一切似乎都不起作用。谁能救我?我是说我该怎么做?谢谢你的阅读

这是根据我得到的回复对我所尝试的内容的更新。 我已经将这个添加到了我的group.setUserAccount(null)中,现在是这个

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

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

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

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

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

另一个抛出一个错误

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

因此,我想我将使用以下方法删除该组:

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

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


共 (2) 个答案

  1. # 1 楼答案

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

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

    所以现在Hibernate知道UserAccount是集合的所有者。现在删除@Pascal时,需要解开两边的绑定。因为Hibernate忽略了集合,所以所有者负责绑定关系,所以像这样的助手方法基本上会在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应该注意级联删除groups

  2. # 2 楼答案

    使用@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)很好,但是

    您是否也将Group中的userAccount引用设置为null

    您仍然必须手动管理Java关系,即如果关系是双向的,则必须在子对象中将父对象设置为null