所以这就是我想要实现的目标,如果可能的话。 我正在尝试使用级联将数据库中的以下对象保存。
这是我遇到的问题的简化示例。我认为它的工作方式是hibernate应该插入" User"那么" Group"然后" UserGroup"按顺序,但正在发生的是它插入"用户"然后" UserGroup"这导致"对象引用未保存的瞬态实例"下面日志中的组错误。
显然,使用自己的save()调用保存单个对象是有效的,但真正的数据库比这大得多,我宁愿避免这种情况。
" TestCode"下面复制数据的来源,从JSON数据中反序列化。
我怀疑它与我的映射有关,但我无法确定原因。
作为参考,我使用的是Hibernate 5.2.10.Final。
那么我错过了什么?
User.java
@Entity
@Table(name = "User")
public class User implements java.io.Serializable {
private static final long serialVersionUID = -7899020279254796671L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "userID", unique = true, nullable = false)
private int userId;
@Column(name = "name", nullable = false, length = 45)
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy = "id.user")
private Set<UserGroup> userGroups = new HashSet<UserGroup>(0);
//Getters, setters, etc...
}
Group.java
@Entity
@Table(name = "Group")
public class Group implements java.io.Serializable {
private static final long serialVersionUID = 4428563096071107683L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "groupID", unique = true, nullable = false)
private int groupId;
@Column(name = "name", nullable = false, length = 45)
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy = "id.group")
private Set<UserGroup> userGroups = new HashSet<UserGroup>(0);
}
UserGroup.java
@Entity
@Table(name = "UserGroup")
public class UserGroup implements java.io.Serializable {
private static final long serialVersionUID = 5495027289164828327L;
@EmbeddedId
private UserGroupId id;
@Column(name = "defaultGroup")
private Boolean defaultGroup;
}
UserGroupdId.java
@Embeddable
public class UserGroupId implements java.io.Serializable {
private static final long serialVersionUID = -3806643465171954306L;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "groupID", nullable = false, insertable = false, updatable = false)
private Group group;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "userID", nullable = false, insertable = false, updatable = false)
private User user;
}
TestCode
User u = new User();
u.setName("User");
Group g = new Group();
g.setName("Group");
UserGroup ug = new UserGroup();
UserGroupId id = new UserGroupId();
ug.setId(id);
ug.getId().setGroup(g);
ug.getId().setUser(u);
ug.setDefaultGroup(false);
u.getUserGroups().add(ug);
session.saveOrUpdate(u);
日志条目
[DEBUG] 2017-08-03 10:19:43.497 [main] SQL - insert into M2M.User (name) values (?)
[DEBUG] 2017-08-03 10:19:43.497 [main] SQL - insert into M2M.User (name) values (?)
[TRACE] 2017-08-03 10:19:43.510 [main] BasicBinder - binding parameter [1] as [VARCHAR] - [User]
[TRACE] 2017-08-03 10:19:43.510 [main] BasicBinder - binding parameter [1] as [VARCHAR] - [User]
[DEBUG] 2017-08-03 10:19:43.541 [main] IdentifierGeneratorHelper - Natively generated identity: 65
[DEBUG] 2017-08-03 10:19:43.541 [main] ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
[DEBUG] 2017-08-03 10:19:43.546 [main] SQL - select usergroup_.groupID, usergroup_.userID, usergroup_.defaultGroup as defaultG1_2_ from M2M.UserGroup usergroup_ where usergroup_.groupID=? and usergroup_.userID=?
[DEBUG] 2017-08-03 10:19:43.546 [main] SQL - select usergroup_.groupID, usergroup_.userID, usergroup_.defaultGroup as defaultG1_2_ from M2M.UserGroup usergroup_ where usergroup_.groupID=? and usergroup_.userID=?
[ERROR] 2017-08-03 10:19:43.546 [main] M2MTest - org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing: m2m.Group
答案 0 :(得分:0)
正如我explained in this article,从@ManyToOne
关联级联是没有意义的。
此外,级联多对多也没有任何意义,因为两个实体都是父实体,而连接表是这两个父关系的子节点。
所以,你有两个选择:
User
和Group
,并在设置关联的两边时级联到UserGroup
。Sets
而不是Lists
。查看this article了解详情。