Reputation: 479
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);
Upvotes: 0
Views: 4215
Reputation: 26572
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.
Upvotes: 1