【问题标题】:Hibernate inserts duplicates after introducing base entityHibernate 在引入基本实体后插入重复项
【发布时间】:2018-04-14 20:18:02
【问题描述】:

我试图在我的 Spring Boot 应用程序中引入一个基本实体,但现在 Hibernate 插入了重复的条目。该应用使用 Spring Data JPA 和 Hibernate 进行持久化。

我之前的代码是这样的:

@Entity
public class PasswordResetCode {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @ManyToOne
    private User user;
    @Column(unique = true)
    private String code;

    public PasswordResetCode(User user, String code) {
        this.user = user;
        user.addPasswordResetCode(this);
        this.code = code;
    }

    // ...

}

@Entity
@Table(name = "\"user\"")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
    private Set<PasswordResetCode> passwordResetCodes = new HashSet<>();

    public void addPasswordResetCode(PasswordResetCode passwordResetCode) {
        this.passwordResetCodes.add(passwordResetCode);
    }

    // ...    
}

我这样创建 PasswordResetCode:

User user = userRepository.findOne(id);
passwordResetCodeRepository.save(new PasswordResetCode(user, "some code"));

这工作得很好,PasswordResetCode 只被插入到数据库中一次,用户对象Set 中的引用被持久化的PasswordResetCode 更新。

现在我引入了BaseEntity,从UserPasswordReset 类中删除了id 字段,并让它们扩展BaseEntityBaseEntity 看起来像这样:

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long id = 0;

    // getter & setter

}

我像以前一样创建了PasswordResetCode,但现在我收到以下错误,因为 Hibernate 尝试插入代码两次:

无法执行语句; SQL [不适用];约束 [“UK_JIAB2A9LLEHA81LWDNYRL9RQ0_INDEX_2 ON PUBLIC.PASSWORD_RESET_CODE(CODE) VALUES ('some code', 115)"

现在我意识到我可以删除User 中的级联或通过User/UserRepository 保存PasswordResetCode,但我想了解发生了什么。

为什么 Hibernate 可以看到 User 集合中的 PasswordResetCode 与他通过存储库保存的相同,尽管它是在持久化之前添加的? 还有为什么加了BaseEntity之后会失败?

【问题讨论】:

    标签: java hibernate spring-boot jpa spring-data-jpa


    【解决方案1】:

    我认为用户 id 是空引用,所以休眠创建一个新的。

    【讨论】:

    • 有道理,但请详细说明,而不是单行,(示例,参考等),以便我们投票:)。
    • 用户对象的值从何而来?会议 ?还是直接数据库?或创建密码更改屏幕并使用 modelAttribute ?如果用户是模型属性并且您使用更改表单并使用 post 方法将数据发送到控制器用户的 id 定义为 null 因为创建新用户实例
    • 正如我所说,我意识到在引入BaseEntity 之后会发生什么。 passwordResetCodeRepository.save 返回一个新对象,该对象现在是持久会话的一部分。 User 仍在引用未持久化的旧对象(仍然具有 id = 0),并且当他持久化用户时,由于级联规则,他休眠创建了重复插入。我的问题是为什么代码在引入 BaseEntity 之前有效,而实体中定义了 id。
    猜你喜欢
    • 2010-12-30
    • 2016-02-14
    • 1970-01-01
    • 2020-10-30
    • 2020-08-16
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 2011-03-27
    相关资源
    最近更新 更多