我的模型看起来像这样:
@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;
}
因此A
和Category
之间存在多对多关系。现在类别是静态的,用户无法更改。在用户界面中,用户将尝试保存实体A
,每个实体可以有一个或多个类别。所以回来的JSON看起来有点像这样:
{A: {categories: [{id: 1}, {id: 2}, {id: 3}]}}
现在当我尝试保存这个A
对象(在jackson已经解组到java之后)时,我只想在连接表A_categories
中为新实体的每个类别创建条目
但是,Category
实体本身也会更新。因此,如果您注意到,JSON没有任何category_name
,因此每个Category
的数据库条目也将更新为名称的null
条目。
如何防止这种情况发生?
答案 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
属性)。
这样,PERSIST
和MERGE
都不会被级联,Hibernate只会使用分离的Category
实例的ID将数据存储到关系表中。
旁注:通常,在多对多关联中级联REMOVE
或ALL
没有意义(如果删除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关系的示例