我在Spring Data JPA中保存多对一字段时遇到问题。 考虑实体用户和组,如下所述:
@Entity
@Table(name = "Users")
public class User {
@Basic(optional = false)
@Column(name = "username")
private String username;
@JoinColumn(name = "group_id", referencedColumnName = "id")
@ManyToOne
private Group group;
}
@Entity
@Table(name = "groups")
public class Group {
@Basic(optional = false)
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "group",cascade=CascadeType.PERSIST)
private Collection<User> userCollection;
}
当我想更新用户实体并在发生异常后使用CrudRepository保存方法更改其组: org.hibernate.HibernateException:Group的实例的标识符从2更改为1和,显示spring数据想要编辑Group的id字段,而它不是正确的 i想要改变它的引用而不是它的id 。
对于Update,我以DTO形式获取视图数据,之后我使用Dozer Mapper将dto对象转换为实体对象,如下所述:
DozerBeanMapper mapper = new DozerBeanMapper();
// get user by id from database for editing
User user = this.userService.findByIdAndDeletedFalse(form.getId());
// merge view data and entity data using Dozer
mapper.map(form, user);
// save User entity
this.userService.save(user);
userService是一个只调用crudRepository save方法的bean。
任何解决方案?
谢谢
答案 0 :(得分:0)
发生错误是因为您尝试更改被跟踪实体的id
,这在JPA中是不允许的。您需要获取对新Group
的引用,并将其分配给User.group
。
简而言之,而不是:
user.getGroup().setId(newId);
试试这个:
user.setGroup(entityManager.getReference(Group.class, newId));
答案 1 :(得分:0)
我认为你应该告诉Dozer
使用以下xml排除group
字段。
<field-exclude>
<a>group</a>
</field-exclude>
并手动设置group
。
mapper.map(form, user);
user.setGroup(this.groupService.finfById(form.group.getId()));
// save User entity
this.userService.save(user);
如果您不想在控制器中映射该组。您可以使用DozerConverter
类来获取group
对象并将其设置在那里。
<mapping>
<class-a>org.mypackage.Form</class-a>
<class-b>org.mypackage.User</class-b>
<field custom-converter-id="org.mypackage.UserGroupCustomConverter">
<a>groupId</a>
<b>group</b>
</field>
</mapping>
public class UserGroupCustomConverter extends DozerConverter<Form, User> {
public NewDozerConverter() {
super(Form.class, User.class);
}
public Boolean convertTo(Form form, User user) {
user.setGroup(this.groupService.finfById(form.group.getId()));
}
}
答案 2 :(得分:0)
这是因为您正在使用临时组。您需要获取您的组,然后将该组分配给您的用户对象。