1

I found this post where it is mentioned that problem can be caused by incorrect equals & hashcode implemantation, but it looks like it isn't... Hibernate 3.6.10 doesn't cascade delete through OneToMany JoinTable

Code (javax.validation.constraints annotations removed)

Author:

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);
        }
}

Email

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);
    }
}

Phone

Phone is similar to Email

Criteria author removing:

    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();
    }

Problem:

When i'm trying to remove author with the code above, hibernate doesn't delete rows in phone & email tables. Only:

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

How I can achieve that Hibernate delete the rows in phone & email tables too? I'm using postgres

1 Answers1

1

I think Criteria make an UPDATE sql statement. Doesn't use Cascade and Envers auditing feature.

You have to find and remove the Entity.

em.remove(em.find(Author.class,author_id));
László Tóth
  • 483
  • 5
  • 15