0

I have a many to many bidirectional relationship in hibernate with entities Book and Author, an Author can write many books and a book can have many authors. the problem appears when trying to save a new book with an author that is already in the database. hibernate will create a new record in the database with the same author with a new id, how can I reference the new book to an existing author in the database instead of creating a new one?

my classes look like this.

@Entity
 @JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "author_id")
private Long id;

@Column(name = "name")
private String name;

@ManyToMany(cascade = CascadeType.ALL, mappedBy = "authors")
private Set<Book> books = new HashSet<>();

book class

@Entity
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "book_id")
private Long id;

@Column(name = "name")
private String name;

@Column(name = "abstract")
private String bookAbstract;


@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
        name = "book_author",
        joinColumns = {@JoinColumn(name = "book_id")},
        inverseJoinColumns = {@JoinColumn(name = "author_id")}
)
private Set<Author> authors = new HashSet<>();

I send an JSON object to the rest controller and then save the book

{
"name" : "Name of the Book",
"bookAbstract" : "an abstract",
"authors" : [
{"name":"Author1"},
{"name":"Author2"},
{"name":"Author3"}]}

I convert the JSON to a java object and the a save it using save() from JPArepository, assuming that Author1 is already in the database, the code below will create a new record of Author1,

Book book = objectMapper.readerFor(Book.class).readValue(input);
bookRepository.save(book);
Rubenex
  • 469
  • 2
  • 8
  • 23
  • Try these: http://stackoverflow.com/questions/19965370/why-is-hibernate-inserting-duplicate-records-every-time-i-run-my-app and http://stackoverflow.com/questions/41063944/spring-hibernate-findbyobject-crudrepository – rj2700 Apr 30 '17 at 18:36

1 Answers1

1

Well the the way i would prevent duplicates in your case would be to:

1) Try to get the records of each of the Authors while. Assuming that you could inject the repository into the mapper then:

Book book = assembleBook(input);

for(String authorName: input.getAuthors){
    Author author = repository.getAuthorByName(authorName);

    if(author == null){
       author = new Author(authorName);
    }

    author.getBooks().add(book);

    book.getAuthors.add(author);
}

2) You may need to perform bookRepository.merge(book);, unless this call is in the same transaction as the one assembling the objects, then bookRepository.saveOrUpdate(book); should do.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63