首页 > 解决方案 > JPA CascadeType Persist 不适用于 spring 数据

问题描述

我有两个实体,用户:

@Data
@EqualsAndHashCode(exclude = "id")
@Entity
@Table(name = "users")
public class User {

    @Id
    @SequenceGenerator(name = "user_id_seq_gen", sequenceName = "users_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_seq_gen")
    private long id;
    @Column(nullable = false, unique = true, length = 100)
    @NotNull
    @Length(min = 4, max = 100)
    private String email;
    @Column(nullable = false, length = 50)
    @NotNull
    @Length(min = 6, max = 100)
    private String password;

}

和验证:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Verification {

    @Id
    @Column(length = 20)
    private String code;

    @OneToOne(cascade = {CascadeType.PERSIST})
    private User user;

}

我用这种方法保存这些实体:

@Transactional
    public void registerUser(User user) {
        user.setPassword(DigestUtils.md5Hex(user.getPassword()));
        String code = RandomStringUtils.random(20, true, true);
        Verification verification;
        while(true) {
            if (!verificationRepository.existsByCode(code)) {
                verification = new Verification(code, user);
                break;
            } else {
                code = RandomStringUtils.random(20, true, true);
            }
        }
        verificationRepository.save(verification);
    }

但是 CascadeType persist 不起作用,它会抛出以下异常:

org.postgresql.util.PSQLException: ERROR: null value in column "user_id" violates not-null constraint
  Подробности: Failing row contains (Oda2AolKrQXYSxuVmclO, null).

但是当我将级联类型更改为 MERGE 时,它可以工作。而且我不明白为什么,因为我同时创建了新用户和新验证。首先我需要保存用户,然后是验证。你知道答案吗?

标签: javajpaspring-data-jpa

解决方案


Spring Data JPA 使用 ID 来确定实例是否是新的。由于您似乎将 id 设置为非空值 Spring Data JPA 将其视为现有实体并调用merge而不是persist.

阅读参考文档中的“保存实体”,了解如何调整该行为。

我建议考虑领域驱动设计和聚合/聚合根,以确定应该通过Cascade.ALL+链接的实体DELETE_ORPHAN以及没有任何级联和单独存储库的实体。

我建议阅读有关该主题的“ Advancing Enterprise DDD ”。


推荐阅读