JPA合并导致外国实体的重复输入

kas*_*ere 0 java merge jpa

问题:

有没有人知道如何合并而不EntityManager试图重新插入外国实体?

场景:

只是为了设置一个与我的案例非常匹配的场景:我有两个实体

@Entity
@Table(name = "login", catalog = "friends", uniqueConstraints =
@UniqueConstraint(columnNames = "username"))
public class Login implements java.io.Serializable{

   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   private Integer id;
   @Column(name = "username", unique = true, nullable = false, length = 50)
   private String username;
   @Column(name = "password", nullable = false, length = 250)
   private String password;
}

@Entity
@Table(name = "friendshiptype", catalog = "friends")
public class FriendshipType implements java.io.Serializable{

   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   private Integer id;
   @OneToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "username")
   private Login login;
      @Column(name = "type", unique = true, length = 32)
   private String type;
   ...//other fields go here
}
Run Code Online (Sandbox Code Playgroud)

无论是Login实体和FriendshipType实体分别保存到数据库.然后,稍后,我需要将Login行与FriendshipType行合并.当我调用时entityManager.merge(friendship),它会尝试插入一个新的Login,当然会导致以下错误

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'myUserName1350319637687' for key 'username'
Error Code: 1062
Call: INSERT INTO friends.login (password, username) VALUES (?, ?)
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何在不让enityManager尝试重新插入外来对象的情况下合并两个对象?

kas*_*ere 5

这是我如何解决问题.我终于想出合并没有解决的原因是因为login.id是由JPA自动生成的.因为我真的不需要自动生成的id字段,所以我将其从模式中删除并username用作@id字段:

@Entity
@Table(name = "login", catalog = "friends", uniqueConstraints =
@UniqueConstraint(columnNames = "username"))
public class Login implements java.io.Serializable{

   private static final long serialVersionUID = 1L;
   @Id
   @Column(name = "username", unique = true, nullable = false, length = 50)
   private String username;
   @Column(name = "password", nullable = false, length = 250)
   private String password;
}
Run Code Online (Sandbox Code Playgroud)

我发现的另一个解决方案,我没有实现,但可以帮助其他人,他们需要有一个自动生成的id字段.

而不是Login为合并创建实例,从数据库中获取实例.我的意思是,而不是

Login login = new Login(); login.setUsername(username); login.setPassword(password);
Run Code Online (Sandbox Code Playgroud)

相反

Login login = loginDao.getByUsername(username);
Run Code Online (Sandbox Code Playgroud)

这样,不会生成新的id字段,使实体看起来不同.

感谢并向所有人提供帮助,特别是@mijer非常耐心.