hibernate实体类设计体会

来源:互联网 发布:名片排版软件 编辑:程序博客网 时间:2024/06/10 03:28

以博客实体类和用户实体类为例,他们之间是多对多的关系,即一个博客可以被多个用户收藏,一个用户也可以收藏多个博客,现在考虑三个问题:
1.双方是否持有对方集合的引用
2.当双方均持有对方集合的引用时,哪一方拥有对于联系的维护权限
3.当双方均持有对方集合的引用时,如何设置级联关系

首先第一个问题,双方是否持有对方的引用。我认为这取决于在传递数据(一方的pojo对象)时是否可能需要同时传递另一方的pojo对象集合。例如,若在传递用户时同时需要传递其收藏的博客列表,则用户类需要持有博客集合的引用,反之亦然。

当双方均持有对方集合的引用时,设有下面用户类和博客类(省略setter和getter方法)

@Entity@Table(name="user_inf")public class User{    //新闻编号,设置为自动增长    @Id@Column(name="user_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer userId;    //新闻的标签    @ManyToMany(targetEntity = Blog.class,cascade=CascadeType.ALL)    @JoinTable(name = "user_blog", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "blog_id") })    private Set<Blog> blogs = new HashSet<Blog>();
@Entity@Table(name="blog_inf")public class Blog {    //新闻编号,设置为自动增长    @Id@Column(name="blog_id")    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Integer blogId;    //mappedBy后面的属性为User类中相应的集合字段名    @ManyToMany(mappedBy="blogs")    private Set<User> user = new HashSet<User>();

现在看第二个问题,当双方均持有对方集合的引用时,哪一方拥有对于联系的维护权限。一方拥有对于联系的维护权限=可以通过对该方对象的修改来修改中间表(多对多关系会产生一个中间表)。例如,若想通过修改用户对象的博客集合这一属性来对中间表进行修改,如下列语句

        //数据库中已存在主键为1的博客记录        Blog blog = new Blog();        blog.setBlogId(1);        //数据库中已存在主键为1的用户记录        User user = new User();        user.setUserId(1);        //为id为1的用户添加收藏id为1的博客        user.getBlogs().add(blog);        sess.update(user);        //执行后中间表user_blog多了一行记录

则应让用户类持有对于联系的维护权限,此时应在博客的用户集合属性的manyToMany注解中添加mappedBy属性,表示博客这一端放弃对联系的维护权限。关于这个问题可以参考一下我的另一篇博客Hibernate注解之@ManyToMany

最后第三个问题,当双方均持有对方集合的引用时,如何设计级联关系。例如,若想在添加用户对象时,同时添加该用户对象持有的博客对象,,如下列语句

        //新的用户对象        User user = new User();        //该用户对象持有两个新的博客对象        user.getBlogs().add(new Blog());        user.getBlogs().add(new Blog());        //同时保存用户对象以及其关联的博客对象        sess.save(user);        //执行后user_inf表多了一行记录        //执行后blog_inf表多了二行记录        //执行后中间表user_blog多了二行记录

此时应在用户的博客集合属性的ManyToMany注解中添加cascade=CascadeType.ALL属性,表示对用户表增加,更新等操作会级联到博客表。

另外在级联操作中有两点需要注意:

1.在级联删除时,若需要在删除用户记录的同时级联删除与其关联的博客记录,则在调用sess.delete(user)方法进行删除时,user对象中必须持有相应博客对象的引用,若user对象中仅有userId属性而blogs属性为空,那么此时只能删除用户记录和中间表内的相关记录,无法级联删除相应的博客记录。
2.在级联操作时,不要通过对放弃维护关联关系的那一方进行级联操作,因为该方不具备修改中间表的权限,而在级联操作中,必然会对中间表进行修改,这样做通常会产生一个由外键约束而导致的异常 。