Search code examples
javajpa-2.0one-to-manyopenjpaapache-tomee

OpenJPA @OneToMany List returning null


I am trying to build a simple Rest Service in which I can add Clients and update them, basically as an experience to learn Java EE technologies. I'm running this application in TomEE and using Eclipse and Maven to code and build it.

In my project, I have the main Entity class we'll refer to as "Clients". With a client, you may have several locations and several contacts, so I have both of these setup as a unidirectional Entity mapping using @OneToMany. I am able to generate the Client with mapping to address and contacts, each of those tables having the ID corresponding back to the Client. When I then go to view the data, all the data in "Client" is there, but just a value of NULL for "Addresses" and "Contacts". I'm using an EJB as the Entity Manager and have a CriteriaQuery setup to get the data.

Client.java

@Entity
public class Client {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @OneToMany(cascade=CascadeType.ALL)
  @JoinColumn(name="vendor_id", referencedColumnName="id")
  private List<ClientAddress> addresses

  @OneToMany(cascade=CascadeType.ALL)
  @JoinColumn(name="vendor_id", referencedColumnName="id")
  private List<ClientContact> contacts

  ...

ClientAddress.java

@Entity
public class ClientAddress {
  ...
}

ClientContacts.java

@Entity
public class ClientContacts {
  ...
}

ClientEntityBroker.java

@Stateless
@Localbean
public class VendorEntityBroker {

    @PersistenceContext(unitName = "client-mysql",
                        type=PersistenceContextType.TRANSACTION)
    private EntityManager em;

    public List<Vendor> getAllClients() {
        CriteriaQuery<Client> cq = em.getCriteriaBuilder().createQuery(Client.class);
        cq.select(cq.from(Client.class));

        return em.createQuery(cq).getResultList();
    }
    ...
}

I do not have a @ManyToOne annotation in either ClientAddress or ClientContacts since its a unidirectional mapping. Database entries all get created but I seem unable to retreive the address and contact data as I expected. I am new to this so I guess I may be querying the data wrong or there is something extra needed on the input for it to be able to properly map on the request.

I am running OpenJPA 2.4 and TomEE 1.7.2.


Solution

  • I think, that you have to fetch the data manually because the default fetch-type of a @OneToMany relationship is FetchType.LAZY.

    You have two options to load the dependent data:

    1. You can define an eager fetchtype by using the annotation @OneToMany in this way:

      @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
      @JoinColumn(name="vendor_id", referencedColumnName="id")
      private List<ClientAddress> addresses
      
    2. You can add a fetch clause to you criteria query.

      CriteriaQuery<Client> cq = em.getCriteriaBuilder().createQuery(Client.class);
      Root<Client> root = cq.from(Client.class)
      root.fetch(Client_.addresses);
      root.fetch(Client_.contacts);
      return em.createQuery(cq).getResultList();