title: JPA persist entities with one to many relation
body: <p>Config</p>
  
  <ul>
  <li>EcliplseLink 2.3.2</li>
  <li>JPA 2.0</li>
  <li>The entities are auto created from the db schema from netbeans with <em>Entity Classes from Database...</em> wizard.</li>
  <li>The controller classes are auto created from netbeans with <em>JPA Controller Classes from Entity Classes...</em> wizard</li>
  </ul>
  
  <p><strong>Short version of question</strong></p>
  
  <p>In a classic scenario, two tables with one to many relation. I create the parent entity, then the child entity and I attach the child to the parent's collection. When I <em>create</em> (controller method) the parent entity, I expect the child entity to be created to and associated with parent. Why doesn't it happen?</p>
  
  <p><strong>Long version</strong></p>
  
  <p>Parent class</p>
  
  <pre><code>@Entity
  @XmlRootElement
  public class Device implements Serializable {
      private static final long serialVersionUID = 1L;
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Basic(optional = false)
      private Integer id;
      @Column(unique=true)
      private String name;
      @Temporal(TemporalType.TIMESTAMP)
      private Date updated;
      @OneToMany(cascade = CascadeType.ALL, mappedBy = "deviceId")
      private Collection&lt;NetworkInterface&gt; networkInterfaceCollection;
  
      public Device() {
      }
  
      public Device(String name) {
          this.name = name;
          updated = new Date();
      }
  
      // setters and getters...
  
      @XmlTransient
      public Collection&lt;NetworkInterface&gt; getNetworkInterfaceCollection() {
          return networkInterfaceCollection;
      }
  
      public void setNetworkInterfaceCollection(Collection&lt;NetworkInterface&gt; networkInterfaceCollection) {
          this.networkInterfaceCollection = networkInterfaceCollection;
      }
  
      public void addNetworkInterface(NetworkInterface net) {
          this.networkInterfaceCollection.add(net);
      }
  
      public void removeNetworkInterface(NetworkInterface net) {
          this.networkInterfaceCollection.remove(net);
      }
      // other methods
  }
  </code></pre>
  
  <p>Child class</p>
  
  <pre><code>@Entity
  @Table(name = "NETWORK_INTERFACE")
  @XmlRootElement
  public class NetworkInterface implements Serializable {
      private static final long serialVersionUID = 1L;
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Basic(optional = false)
      private Integer id;
      private String name;
      @Temporal(TemporalType.TIMESTAMP)
      private Date updated;
      @JoinColumn(name = "DEVICE_ID", referencedColumnName = "ID")
      @ManyToOne(optional = false)
      private Device deviceId;
  
      public NetworkInterface() {
      }
  
      public NetworkInterface(String name) {
          this.name = name;
          this.updated = new Date();
      }
  
      // setter and getter methods...
  
      public Device getDeviceId() {
          return deviceId;
      }
  
      public void setDeviceId(Device deviceId) {
          this.deviceId = deviceId;
      }
  }
  </code></pre>
  
  <p>Main class</p>
  
  <pre><code>public class Main {
      public static void main(String[] args) {
          EntityManagerFactory emf = Persistence.createEntityManagerFactory("wifi-dbPU");
          DeviceJpaController deviceController = new DeviceJpaController(emf);
          NetworkInterfaceJpaController netController = new NetworkInterfaceJpaController(emf);
  
          Device device = new Device("laptop");
          NetworkInterface net = new NetworkInterface("eth0");
  
          device.getNetworkInterfaceCollection().add(net);
          deviceController.create(device);
      }
  }
  </code></pre>
  
  <p>This class throws a NullPointerException in line: <code>device.getNetworkInterfaceCollection().add(net);</code></p>
  
  <p>The system knows that there is a new entity <code>device</code> and it has an element <code>net</code> in it's collection. I expected it to write <code>device</code> in db, get device's id, attach it to <code>net</code> and write it in db.</p>
  
  <p>Instead of this, I found that these are the steps I have to do:</p>
  
  <pre><code>deviceController.create(device);
  net.setDeviceId(device);
  device.getNetworkInterfaceCollection().add(net);
  netController.create(net);
  </code></pre>
  
  <p><strong>Why do I have to create the child when the parent class knows it's child and it should create it for me?</strong></p>
  
  <p>The create method from DeviceJpaController (sorry for the long names in fields, they are auto generated).</p>
  
  <pre><code>public EntityManager getEntityManager() {
      return emf.createEntityManager();
  }
  
  public void create(Device device) {
      if (device.getNetworkInterfaceCollection() == null) {
          device.setNetworkInterfaceCollection(new ArrayList&lt;NetworkInterface&gt;());
      }
      EntityManager em = null;
      try {
          em = getEntityManager();
          em.getTransaction().begin();
          Collection&lt;NetworkInterface&gt; attachedNetworkInterfaceCollection = new ArrayList&lt;NetworkInterface&gt;();
          for (NetworkInterface networkInterfaceCollectionNetworkInterfaceToAttach : device.getNetworkInterfaceCollection()) {
              networkInterfaceCollectionNetworkInterfaceToAttach = em.getReference(networkInterfaceCollectionNetworkInterfaceToAttach.getClass(), networkInterfaceCollectionNetworkInterfaceToAttach.getId());
              attachedNetworkInterfaceCollection.add(networkInterfaceCollectionNetworkInterfaceToAttach);
          }
          device.setNetworkInterfaceCollection(attachedNetworkInterfaceCollection);
          em.persist(device);
          for (NetworkInterface networkInterfaceCollectionNetworkInterface : device.getNetworkInterfaceCollection()) {
              Device oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface = networkInterfaceCollectionNetworkInterface.getDeviceId();
              networkInterfaceCollectionNetworkInterface.setDeviceId(device);
              networkInterfaceCollectionNetworkInterface = em.merge(networkInterfaceCollectionNetworkInterface);
              if (oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface != null) {
                  oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface.getNetworkInterfaceCollection().remove(networkInterfaceCollectionNetworkInterface);
                  oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface = em.merge(oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface);
              }
          }
          em.getTransaction().commit();
      } finally {
          if (em != null) {
              em.close();
          }
      }
  }
  </code></pre>