Hibernate:OneToMany / ManyToOne,带有额外的列级联

时间:2016-02-09 09:25:25

标签: java hibernate

让我们举一个简单而众所周知的例子:用户和群组。

用户可以在多个组中,因为一个组可以拥有许多用户。但在这种情况下,我们希望处理用户输入组的日期。

所以我们会:

表User:

@Entity
public class User extends com.example.UserItf {

    public User() { /* not needed */ }

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Override
    public Long getId(){
        return _id;
    }

    /* some other fields like name, etc. */

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
    @OrderBy("id")
    @Override
    public List<Group> getGroups(){
        return _groups;
    }
}

表UserGroups:

@Entity
public class UserGroups extends com.example.UserGroupsItf {

    public UserGroups(){ /* not needed */ }

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Override
    public Long getId(){
        return _id;
    }

    @ManyToOne
    @JoinColumn(name="userid")
    @Override
    public User getUser() {
        return _user;
    }

    @ManyToOne
    @JoinColumn(name="groupid")
    @Override
    public Group getGroup() {
        return _group;
    }

    @Override
    public Date getEntryDate(){
        return _date; // only to represent a cross table with extra column
    }
}

表格组:

@Entity
public class Group extends com.example.GroupItf {

    public Group() { /* not needed */ }

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Override
    public Long getId(){
        return _id;
    }

    /* some other fields like name, etc. */

    @OneToMany(mappedBy = "group", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
    @OrderBy("id")
    @Override
    public List<User> getUsers(){
        return _users;
    }
}

我当前的情况是一样的,我面临的问题如下:我想为一个选定的用户添加一个组,所以步骤(如果我错了,请纠正我):

  1. 获取所需用户(已完成)
  2. 获取所需的组(从数据库中检索的列表)
  3. 将群组添加到用户列表
  4. 坚持用户
  5. 这将导致添加/更新具有组的用户,因此也在UserGroups中创建一个条目,对吗?

    现在,我想从用户中删除该组,所以:

    1. 获取所需用户(已完成)
    2. 取消选择列表中的组
    3. 这将从用户群组中删除(user.getGroups().remove(grp)
    4. 坚持用户
    5. 我的问题是UserGroups中的条目仍然存在。我已经使用了Cascades,但我没有所需的行为:通过从用户中删除一个组,这也会删除表中的组(更新:它不会删除分组,但它也不会删除UserGroups中的链接。

      我只想删除&#34;交叉表中的关系和额外的列&#34;如果,从一方或另一方面,我删除了用户和组之间的链接。

      我已经浏览了Hibernate和StackOverflow,但似乎没有什么能适合我的情况。请注意,我提供的表的代码正是我项目中的代码。

      例如,是否可以仅从用户端删除链接,并将其级联以删除UserGroups关系?或者我是否必须单独管理每个实体?

      ___编辑___

      向用户添加组时,这是Hibernate输出。请注意,这是一个示例,因此我将输出格式化为与示例匹配,但没有其他任何内容被修改。

      DEBUG [org.hibernate.SQL] 
          insert 
          into
              UserGroups
              (groupId, entryDate, userId, userGroupsId) 
          values
              (?, ?, ?, ?)
      TRACE [descriptor.sql.BasicBinder] binding parameter [1] as [BIGINT] - [1]
      TRACE [descriptor.sql.BasicBinder] binding parameter [2] as [DATE] - [xxx] // added to match the example, this is an other field here (boolean)
      TRACE [descriptor.sql.BasicBinder] binding parameter [3] as [BIGINT] - [1]
      TRACE [descriptor.sql.BasicBinder] binding parameter [4] as [BIGINT] - [7]
      

      而且,令人惊讶的是,在启用日志记录输出后,我发现删除没有输出。那可能是EntityManager认为实体没有改变吗?

      持久保存用户的功能执行以下操作:

      _entityManager.getTransaction().begin();
      _entityManager.persist( user );
      _entityManager.getTransaction().commit();
      

      另外,多亏了@Dragan Bozanovic,似乎这个场景并不适合这个问题。在这里,没有任何变化,没有任何动作,UserGroups链接也是如此。

2 个答案:

答案 0 :(得分:2)

只是为了突出我的问题(这可能可以挽救别人的生命)我的问题只是一个编码问题。

我在代码中看到,在一个实体中我使用的是Hibernate的CascadeTypes,另一方面我使用的是Java级联。

// This is the cascade provided by javax.persistence.CascadeType
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
@OrderBy("id")
@Override
public List<User> getUsers(){
    return _users;
}

VS

// This is the cascade provided by org.hibernate.annotations
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
@OrderBy("id")
@Override
public List<User> getUsers(){
    return _users;
}

当然,我的问题显然是我对这些缺乏了解,所以也许这可能是其他人的暗示。

答案 1 :(得分:0)

  

是否可以仅从用户端删除链接   例如,并级联它以删除UserGroups关系?或者我   必须分别管理每个实体吗?

可以满足此要求,但看起来您需要更新一些代码和映射。

请浏览以下链接http://www.codejava.net/frameworks/hibernate/hibernate-many-to-many-association-with-extra-columns-in-join-table-example,我认为它应该有助于满足您的要求。