0

My question is very simple ..

  1. Let's say there are 2 classes .. Book and Author
  2. Let's assume that a book can ONLY be written by 1 author.
  3. An author can write many books.
  4. Let's assume author has unique name. [No 2 authors can have same name]

Now .. assuming all the hibernate\JPA configs are done.

From main method - I save Book book1 having name "book1" and author name "author1"

If I put cascade as ALL .. both book and author gets saved upon saving book.

Problem

Now, If I save another book with same author - it is saving both book and author again. This means I am ending up with 2 same authors.

What I have done

  1. I have replace cascade ALL with MERGE.
  2. Before assigning author to book - I am checking DB for the name -

a. If I get a response - I assigned the retrieved author to the book and SAVE the book.

b. If I don't get any result - I assign the author to the book and save BOTH author and book.

This way I am able to solve my problem.

But is it the right way ?

@Entity class Book{ @Id private Long bookId; private String name; @OneToOne private Author author; } @Entity class Author{ @Id private Long authorId; private String name; } 

Main Code

public static void main(String[] args) { ApplicationContext context = SpringApplication.run(BeanConfiguration.class, args); BookRepository bookRepo = context.getBean(BookRepository.class); AuthorRepository authorRepo = context.getBean(AuthorRepository.class); Book b1 = new Book(); b1.setBookName("book1"); Author a1 = new Author(); a1.setAuthorName("author1"); Author authorFromDatabase = authorRepo.findByAuthorName(a1.getAuthorName()); if (authorFromDatabase == null) { b1.setAuthor(a1); authorRepo.save(a1); } else { b1.setAuthor(authorFromDatabase); } bookRepo.save(b1); } 

Update It is not that simple.. For example .. Please think about the association between .. Customer and Address .. customer can have one or many address .. and if a new customer is sharing address with other customer .. then don't make the persist on address .. just assign the the address(id) to the new customer.

My question is what i did above , i.e. to search for existing author (or address in above case) is the right approach ? .. to avoid duplicate rows in the Author (or Address table)

5
  • 1
    Welcome to Stack Overflow, please read How do I ask a good question? specifically the "Write a title that summarizes the specific problem" section. Commented Jul 15, 2016 at 7:10
  • Add the code that is writing the objects to the database. I also doubt that this are your actual objects I'm missing getter/setter and equals/hashCode implementations. Commented Jul 15, 2016 at 7:24
  • Added to the main post Commented Jul 15, 2016 at 7:45
  • Using saveOrUpdate instead of save doesn't help? Commented Jul 15, 2016 at 8:11
  • Please read the "Update" part .. saveOrUpdate won't help Commented Jul 15, 2016 at 8:47

1 Answer 1

3

If Author can have many Book It is not @OneToOne association, but @OneToMany association.

@Entity class Book{ @Id @GeneratedValue private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) private Author author; } @Entity class Author{ @Id @GeneratedValue private Long id; private String name; @OneToMany(mappedBy = "author") private List<Book> books = new ArrayList<Book>(); } 

The simplest way to add books to the Author

Author author = new Author(); save(author); Book book = new Book(); book.setAuthor(author); save(book); Book goodBook = new Book(); goodBook.setAuthor(author); save(goodBook); 

The Book is not a reference value (I mean a catalog, a reference table), so we can use an association via the foreign key on the Book part.

If you need to work with reference values like Customer and Address (a reference), you should use a join table.

@Entity class Address { @Id @GeneratedValue private Long id; } @Entity class Customer{ @Id @GeneratedValue private Long id; private String name; @OneToMany private List<Address> addresses = new ArrayList<Address>(); } 
Sign up to request clarification or add additional context in comments.

5 Comments

Hmm .. it is not that simple.. For example .. Customer and Address .. customer can have one or many address .. and if a new customer is sharing address with other customer .. then dont make the persist on address .. just assign the the address(id) to the new customer.
Thanks, but my question is different. .. the mappings will not save duplicates automatically .. right ? We would have to take care of that ourselves .. by looking up first in the database .. like I have done in the main method .. copied-pasted above .. Please note that my question is not about mappings .. it is about avoiding duplicates in the "mapped" entity.
@reverse Yes, you should carry about duplicates yourself.
In your example .. you know the author object (its content).. now imagine author details are coming from some WS and you dont know if it already exists in the database .. then you would HAVE to do a find to check its existence .. My question was .. is there a better way ? or what I have done is correct ..
@reverse It is correct: then you would HAVE to do a find to check its existence.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.