【问题标题】:Hibernate Cascade.REMOVE doesn't work with CriteriaHibernate Cascade.REMOVE 不适用于 Criteria
【发布时间】:2021-11-13 05:48:37
【问题描述】:

我发现这篇文章提到问题可能是由不正确的等号和哈希码实现引起的,但看起来不是...... Hibernate 3.6.10 doesn't cascade delete through OneToMany JoinTable

代码(javax.validation.constraints 注解被移除)

作者:

import org.bulletin_board.domain.address.Address;
import lombok.*;
import lombok.experimental.FieldDefaults;

import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;

@Entity
@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Builder
public class Author {
        @Id
        @Column(name = "author_id", updatable = false)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        int id;

        @Column(name = "first_name")
        String firstName;

        @Column(name = "last_name")
        String lastName;

        int age;

        @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
                fetch = FetchType.EAGER,
                orphanRemoval = true)
        @JoinColumn(name = "FK_Author_Address")
        Address address;

        @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
                orphanRemoval = true)
        @JoinTable(name = "Author_Email",
                joinColumns = @JoinColumn(name = "author_id"),
                inverseJoinColumns = @JoinColumn(name = "email_id"),
                uniqueConstraints = @UniqueConstraint(columnNames = "author_id"))
        List<Email> emails;

        @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
                orphanRemoval = true)
        @JoinTable(name = "Author_Phone",
                joinColumns = @JoinColumn(name = "author_id"),
                inverseJoinColumns = @JoinColumn(name = "phone_id"),
                uniqueConstraints = @UniqueConstraint(columnNames = "author_id"))
        List<Phone> phones;

        @Override
        public String toString() {
                return "Author:" +
                        "id = " + id +
                        ", firstName = '" + firstName + '\'' +
                        ", lastName = '" + lastName + '\'' +
                        ", age = " + age +
                        ", address = " + address +
                        ", \nemails: " + emails +
                        ", \nphones:" + phones;
        }

        @Override
        public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
                Author author = (Author) o;
                return id == author.id && age == author.age && firstName.equals(author.firstName) && lastName.equals(author.lastName) && address.equals(author.address) && emails.equals(author.emails) && phones.equals(author.phones);
        }

        @Override
        public int hashCode() {
                return Objects.hash(id, firstName, lastName, age, address, emails, phones);
        }
}

电子邮件

import lombok.*;
import lombok.experimental.FieldDefaults;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Objects;

@Entity
@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Builder

public class Email {
    @Id
    @Column(name = "email_id", updatable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;

    String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Email email = (Email) o;
        return id == email.id && name.equals(email.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

电话

电话类似于电子邮件

标准作者删除:

    public void deleteById(int id) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaDelete<Author> delete = cb.createCriteriaDelete(Author.class);
        Root<Author> root = delete.from(Author.class);

        delete.where(cb.equal(root.get(Author_.id), id));
        em.createQuery(delete).executeUpdate();
    }

问题:

当我尝试使用上面的代码删除作者时,hibernate 不会删除电话和电子邮件表中的行。仅:

Hibernate: delete from Author_Email where (author_id) in (select author_id from Author where author_id=1)

Hibernate: delete from Author_Phone where (author_id) in (select author_id from Author where author_id=1)

Hibernate: delete from Author where author_id=1

如何实现 Hibernate 也删除电话和电子邮件表中的行? 我正在使用 postgres

【问题讨论】:

    标签: java postgresql hibernate jpa


    【解决方案1】:

    我认为 Criteria 会创建一个 UPDATE sql 语句。 不使用 Cascade 和 Envers 审计功能。

    您必须找到并删除实体。

    em.remove(em.find(Author.class,author_id));
    

    【讨论】:

    • 没错!更新和删除正在绕过 JPA 功能
    • 成功了!使用条件连接来实现相同的结果是否有任何意义?
    • 您可以在数据库上使用 on delete Before 触发器。我不知道其他解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 2017-03-09
    • 1970-01-01
    相关资源
    最近更新 更多