【发布时间】:2017-10-30 02:54:39
【问题描述】:
我的帐户和组之间存在多对多关系。组表的数据已预先填充,无需添加其他组。
使用 Hibernate,我的愿望是:
- 将帐户添加到帐户表中,
- 在 account_group 表中添加一条记录,然后
- 不向组表中添加记录
在我看来,无论我做什么,我总是在组表中得到重复记录。这是我的问题。这是我的代码:
Account.java
@Entity
@Table(name = "account", schema = "admin")
public class Account {
@Id
@GeneratedValue
private UUID id;
...
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinTable(name = "account_grouping", schema = "admin", joinColumns = @JoinColumn(name = "account_id"), inverseJoinColumns = @JoinColumn(name = "grouping_id"))
private Set<Grouping> groupings;
...
// getters and setters
}
Grouping.java
@Entity
@Table(name = "grouping", schema = "admin")
public class Grouping {
...
@Id
@GeneratedValue
private UUID id;
...
// getters and setters
}
AccountDao.java
@Repository
public class AccountDao extends AbstractJpaDao<Account, String> {
...
@Transactional
public boolean create(Account newAccount) {
try {
getEntityManager().merge(newAccount);
return true;
} catch(Exception e) {
System.out.println("Danger, Will Robinson!: " + e);
return false;
}
}
}
我查找了许多有关 Hibernate @ManyToMany 示例的问题和网站,但我一定遗漏了一些东西。感谢您的阅读和帮助。
【问题讨论】:
-
为什么你有一个级联来合并和持久化,因为你完全不想添加或更新一个新组?删除它。然后在保存之前发布实际创建帐户并向其添加组的代码。
-
如果我没有指定任何 CascadeType,它会给我以下错误:
Error during managed flush [org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing -
我应该提到 Jackson 正在序列化来自前端的 JSON 响应,该响应成为上面的 newAccount 变量。 JSON 中的分组变量如下所示:
groupings: [{name: "groupa", groupType: "typea"}] -
这个错误是相当强烈的提示。它告诉您:“您正在将一个新的非持久组保存为帐户的一部分”。你恰恰不想那样。通过添加级联,您可以让 Hibernate 在保存帐户的同时保存这个新组。处理此错误的正确方法是避免传递一个新组,而是传递一个现有组,这正是您想要的。 Hibernate 使用 ID 识别实体。您保存在帐户中的组没有。
-
我觉得自己很蠢!就是这样!我只需要在发送到后端的 JSON 响应正文中包含组的 ID。由于您是第一个发布解决方案的人,如果您将解决方案发布为答案,我会将其标记为正确答案。
标签: java hibernate many-to-many