Spring数据更新多对一属性

时间:2017-02-12 19:32:51

标签: java spring hibernate spring-mvc jpa

我在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。

任何解决方案?

谢谢

3 个答案:

答案 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)

这是因为您正在使用临时组。您需要获取您的组,然后将该组分配给您的用户对象。