Hibernate插入导致另一个表

时间:2016-03-16 14:51:18

标签: spring hibernate jpa

我的模型看起来像这样:

@Entity
@Table(name = "A")
class A {
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "A_categories", joinColumns = {
        @JoinColumn(name = "A_id", nullable = false, updatable = false) },
        inverseJoinColumns = { @JoinColumn(name = "category_id",
                nullable = false, updatable = false) })
    private List<Category> categories;

}

@Entity
@Table(name = "category")
class Category {
     @Id
     @Column(name="id")
     @GeneratedValue
     private Integer id;

     @Column(name = "category_name")
     private String categoryName;

     @ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories")
     private List<A> a;

}

因此ACategory之间存在多对多关系。现在类别是静态的,用户无法更改。在用户界面中,用户将尝试保存实体A,每个实体可以有一个或多个类别。所以回来的JSON看起来有点像这样:

{A: {categories: [{id: 1}, {id: 2}, {id: 3}]}}

现在当我尝试保存这个A对象(在jackson已经解组到java之后)时,我只想在连接表A_categories中为新实体的每个类别创建条目

但是,Category实体本身也会更新。因此,如果您注意到,JSON没有任何category_name,因此每个Category的数据库条目也将更新为名称的null条目。

如何防止这种情况发生?

3 个答案:

答案 0 :(得分:1)

两种不同的方法:

1)在合并之前设置托管类别。

a.setCategories(readAllByIds(a.getCategories()))

private Collection<Category> readAllByIds(Collection<Category> categories) {
  Collection<Category> result = new ArrayList();
  for (Category category : categories) {
    result.add(entityManager.getReference(Category.class, category.getId()));
  }
  return result;
}

EntityManager.getReference返回代理,因此额外的好处是没有执行数据库往返来读取相关类别。

使用此解决方案,您不会将反序列化的类别合并到持久性上下文中,因此Hibernate不会将其状态与数据库同步。

2)请勿将任何操作从A级联到categories (删除cascade属性)。

这样,PERSISTMERGE都不会被级联,Hibernate只会使用分离的Category实例的ID将数据存储到关系表中。

旁注:通常,在多对多关联中级联REMOVEALL没有意义(如果删除A,您可能不想删除所有它属于的类别。)

答案 1 :(得分:0)

@Column具有可插入和可更新的属性。您可以将它们设置为false:

@Entity
@Table(name = "category")
class Category {
     @Id
     @Column(name="id", insertable=false, updatable=false)
     @GeneratedValue
     private Integer id;

     @Column(name = "category_name", insertable=false, updatable=false)
     private String categoryName;

     @ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories")
     private List<A> a;

}

答案 2 :(得分:0)

您可以尝试添加此

@Entity
@Table(name = "category")
class Category {
 @Id
 @Column(name="id")
 @GeneratedValue
 private Integer id;

 @Column(name = "category_name")
 private String categoryName;

 @ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories", cascade=CascadeType.DETACH)
 private List<A> a;

}

使用cascade.DETACH在保存实体时不应保存更改,但请告诉我是否无法通过此DETACH操作修改ManyToMany关系的示例