spring data jpa复合键重复键记录插入导致更新

Mas*_*ode 5 java spring jpa spring-data spring-data-jpa

我有一个具有复合键的实体,我试图通过使用 spring data jpa 存储库到 mysql 数据库来持久化它,如下所示:

@Embeddable
public class MobileVerificationKey implements Serializable{
private static final long serialVersionUID = 1L;

@Column(name="CUSTOMERID")
private Long customerId;

@Column(name="CUSTOMERTYPE")
private Integer customerType;

@Column(name="MOBILE")
private Long mobile;
@Embeddable
public class MobileVerificationKey implements Serializable{

    private static final long serialVersionUID = 1L;

    @Column(name="CUSTOMERID")
    private Long customerId;

    @Column(name="CUSTOMERTYPE")
    private Integer customerType;

    @Column(name="MOBILE")
    private Long mobile;
//getter and setters
}
Run Code Online (Sandbox Code Playgroud)

和实体作为

@Entity
@Table(name="mobileverificationdetails")
public class MobileVerificationDetails {

    @EmbeddedId
    private MobileVerificationKey key;

    @Column(name="MOBILETYPE")
    private String mobileType;

    @Column(name="MOBILEPIN")
    private Integer mobilePin;
//getters and setters

}
Run Code Online (Sandbox Code Playgroud)

我的 spring data jpa 存储库如下所示:

public interface MobileVerificationDetailsRepository extends
        CrudRepository<MobileVerificationDetails, MobileVerificationKey> {

    @Override
    MobileVerificationDetails save(MobileVerificationDetails mobileVerificationDetails);

    @Override
    MobileVerificationDetails  findOne(MobileVerificationKey id);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我尝试添加原始记录具有相同键而其他字段具有不同值的重复记录。当我尝试插入第二条记录时,它会导致使用新值更新现有记录,而不是因违反主键约束而引发异常。 .任何人都可以向我解释一下这种行为吗?

Oli*_*ohm 4

解决这个问题最简单(也是侵入性最小)的方法可能是确保 id 仅在持久化之前设置。这可以通过以下方式实现:@PrePersist

\n\n
abstract class MobileVerificationDetails {\n\n  @EmbeddedId\n  private MobileVerificationKey id;\n\n  @PrePersist\n  void initIdentifier() {\n\n    if (id == null) {\n      this.id = \xe2\x80\xa6 // Create ID instance here.\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,您可以persist(\xe2\x80\xa6)通过相应地实施Persistable和实施来强制使用isNew()。确保此方法true在第一次插入时返回。我们通常看到人们持有一个瞬态布尔标志,该标志在@PostPersist/@PostLoad注释的方法中更新。

\n\n
abstract class AbstractEntity<ID extends Serializable> implements Persistable<ID> {\n\n  private @Transient boolean isNew = true;\n\n  @Override\n  public boolean isNew() {\n    return isNew;\n  }\n\n  @PostPersist\n  @PostLoad\n  void markNotNew() {\n    this.isNew = false;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n