'Java Hibernate many-to-many bidirectional inserting results in strange behaviour

i have next very simple entities (Author and Book) with many-to-many relationship:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "authors")
@SequenceGenerator(name="author_id_seq_generator", sequenceName="author_id_seq", allocationSize = 1)
public class AuthorEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    Long id;
    @Column(name = "surname")
    String surname;
    @Column(name = "name")
    String name;

    @ManyToMany(mappedBy = "authors")
    Set<BookEntity> books;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "books")
@SequenceGenerator(name="book_id_seq_generator", sequenceName="book_id_seq", allocationSize = 1)
public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;
    @Column(name = "title")
    private String title;
    @Column(name = "price")
    private Double price;

    @ManyToMany
            @JoinTable(
                    name = "Books_To_Authors",
                    joinColumns = @JoinColumn(name = "book_id"),
                    inverseJoinColumns = @JoinColumn(name = "author_id")
            )
    Set<AuthorEntity> authors;
}

Then in my repository i receive a request type of

@Value
public class AuthorWithKnownBooksRequest {
    String surname;
    String name;
    List<Long> bookIds;
}

and here is the method:

@Override
    @Transactional
    public void addBookWithKnownAuthors(BookWithKnownAuthors bookWithKnownAuthors) {
        // get authors
        MultiIdentifierLoadAccess<AuthorEntity> multiLoadAccess = entityManager.unwrap(Session.class).byMultipleIds(AuthorEntity.class);
        List<AuthorEntity> authors = multiLoadAccess.multiLoad(bookWithKnownAuthors.getAuthorIds());
        // to avoid infinite recursion
        authors.stream().forEach(author -> author.setBooks(null));
        // create book entity
        BookEntity be = new BookEntity();
        be.setPrice(bookWithKnownAuthors.getPrice());
        be.setTitle(bookWithKnownAuthors.getTitle());
        be.setAuthors(authors.stream().collect(Collectors.toSet()));
        // save to db
        entityManager.persist(be);
    }

and it works fine,

Hibernate: select authorenti0_.id as id1_0_0_, authorenti0_.name as name2_0_0_, authorenti0_.surname as surname3_0_0_ from authors authorenti0_ where authorenti0_.id in (?, ?, ?)
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into books (price, title, id) values (?, ?, ?)
Hibernate: insert into books_to_authors (book_id, author_id) values (?, ?)
Hibernate: insert into books_to_authors (book_id, author_id) values (?, ?)
Hibernate: insert into books_to_authors (book_id, author_id) values (?, ?)

however if I'm trying to do the same thing from author's side, it behaves strangely

@Override
    @Transactional
    public void addAuthorWithKnownBooks(AuthorWithKnownBooks authorWithKnownBooks) {
        MultiIdentifierLoadAccess<BookEntity> multiLoadAccess = entityManager.unwrap(Session.class).byMultipleIds(BookEntity.class);
        List<BookEntity> books = multiLoadAccess.multiLoad(authorWithKnownBooks.getBookIds());
        // to avoid infinite recursion
        books.stream().forEach(book -> book.setAuthors(null));
        // create author entity
        AuthorEntity ae = new AuthorEntity();
        ae.setName(authorWithKnownBooks.getName());
        ae.setSurname(authorWithKnownBooks.getSurname());
        ae.setBooks(books.stream().collect(Collectors.toSet()));
        // save to db
        entityManager.persist(ae);
    }

The result is instead of inserting I get deleting of rows from connection table.

Hibernate: select bookentity0_.id as id1_1_0_, bookentity0_.price as price2_1_0_, bookentity0_.title as title3_1_0_ from books bookentity0_ where bookentity0_.id in (?, ?, ?)
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into authors (name, surname, id) values (?, ?, ?)
Hibernate: delete from books_to_authors where book_id=?
Hibernate: delete from books_to_authors where book_id=?
Hibernate: delete from books_to_authors where book_id=?

It looks to me as if the problem is with the owner side, because if I change @ManyToMany in BookEntity and AuthorEntity the other way around it works for Authors but doesn't work for Books

Can anyone explain to me how I can fix it? or the way it should be done? I feel like i'm missing some important concept.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source