简体   繁体   中英

JPA OneToMany - Collection is null

I'm trying to set up a bidirectional relationship using JPA. I understand that it's the responsability of the application to maintain both sides of the relationship.

For example, a Library has multiple Books. In the Library-entity I have:

@Entity
public class Library {
  ..
  @OneToMany(mappedBy = "library", cascade = CascadeType.ALL)
  private Collection<Book> books;

  public void addBook(Book b) {
    this.books.add(b);
    if(b.getLibrary() != this)
      b.setLibrary(this);
  }
  ..
}

The Book-entity is:

@Entity
public class Book {
  ..
  @ManyToOne
  @JoinColumn(name = "LibraryId")
  private Library library;

  public void setLibrary(Library l) {
    this.library = l;
    if(!this.library.getBooks().contains(this))
      this.library.getBooks().add(this);
  }
  ..
}

Unfortunately, the collection at the OneToMany-side is null. So for example a call to setLibrary() fails because this.library.getBooks().contains(this) results in a NullPointerException.

Is this normal behavior? Should I instantiate the collection myself (which seems a bit strange), or are there other solutions?

Entities are Java objects. The basic rules of Java aren't changed just because there is an @Entity annotation on the class.

So, if you instantiate an object and its constructor doesn't initialize one of the fields, this field is initialized to null.

Yes, it's your responsibility to make sure that the constructor initializes the collection, or that all the methods deal with the nullability of the field.

If you get an instance of this entity from the database (using em.find(), a query, or by navigating through associations of attached entities), the collection will never be null, because JPA will always initialize the collection.

It seems that books type of Collection in Library class is not initilized. It is null;

So when class addBook method to add a book object to collection. It cause NullPointerException.

@OneToMany(mappedBy = "library", cascade = CascadeType.ALL)
 private Collection<Book> books;

 public void addBook(Book b) {
    this.books.add(b);
    if(b.getLibrary() != this)
    b.setLibrary(this);
 }

Initilize it and have a try.

Change

private Collection<Book> books;

To

private Collection<Book> books = new ArrayList<Book>();

Try to set the fetch type association property to eager on the OneToMany side. Indeed, you may leave this part (this.library.getBooks().add(this)) to be written within a session:

Library l = new Library();    
Book b = new Book();
b.setLibrary(l);
l.getBooks().add(b);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM