JPA How can I get the generated id/object when using merge from parent but child is created?

前端 未结 4 1542
孤独总比滥情好
孤独总比滥情好 2021-01-04 20:47

I have an entity that has been previously persited and has a @OneToMany relationship with another entity. In order to add a new entity I just add my new entity

相关标签:
4条回答
  • 2021-01-04 20:52

    I had a similar problem with persistence provider eclipselink. I needed to add new orders from a client database with temporary "client orderIDs" to an existing customer in a server database. Because I needed the "server orderIDs" for further client requests, i wanted to create a map (clientID, serverID) and send it back to the client. Basically my approach is to get a reference to the copy of the newly added child order. It will always be added to the end of my list in parent class customer, that fact is used to retrieve it.

    I use the entity classes Customer and Order, where Customer has a List (LinkedList) of orders.

    Parent Customer class: ...

        @OneToMany(mappedBy = "customer", cascade=CascadeType.ALL, orphanRemoval = true)
        private List<Order> orders = new LinkedList<Order>();
    
        public Order getLastOrder() {
          return orders.get(orders.size()-1);
        }
    

    Child Order class:

        @ManyToOne(optional=false)
        private Customer customer;
    

    Servlet:

        Customer customer = customerService.findByID(customerID); //existing customer
        Order order = new Order();
        //add attributes to new order
        customer.addOrder(order);
        customerService.update(customer); //generates keys for children
        order = customer.getLastOrder();
        Long orderID = order.getID; //Nullpointer exception
    

    CustomerService updates customer with EntityManager.merge but I forgot to update the reference in the servlet:

    CustomerService class:

        public void update(Customer entity) {
          entityManager.merge(entity);
        }  
    

    I solved it this way: CustomerService class:

        public Customer update(Customer entity) {
          return entityManager.merge(entity);
        }
    

    Servlet: ....

        customer = customerService.update(customer); //generates keys for children
    

    Now everything works fine.

    0 讨论(0)
  • 2021-01-04 20:52

    Make sure that you are setting both sites of the relationship before persisting the changes.

    child.setParent(parent);
    parent.getChildren().add(child);
    Parent parentWithId = em.merge(parent);
    em.flush(); // make sure that the persistence context and database are in sync
    parentWithId.getId(); // works
    parentWithId.getChildren().get(0).getId(); // should also work
    
    0 讨论(0)
  • 2021-01-04 21:00

    Stackoverflow post and JPA documentation have the answer provided that you do your research.

    The way to do what I want is to use persist on the managed parent. This will ignore any changes on the parent, but will cascade persist (provided that it is set up to cascade). The child object will have the correct id afterwards.

    ....
    JPAEntity newObject=new JPAEntity();
    managedObject.addChild(newObject);
    em.persist(managedObject)
    newObject.getId() //work fine!
    
    0 讨论(0)
  • 2021-01-04 21:12

    You should be able to "see" a generated ID for a new Entity:

    • after transaction commits, or

    • after a em.flush() (where em is your EntityManager) while a transaction is active.

    Note also that all relationships between Entities need to be resolved in the Java data structures prior persistence. Child references to parents need to be "set", and vice-versa.

    0 讨论(0)
提交回复
热议问题