Pregunta

I have the following code:

public class Parent{
   @OneToMany(mappedBy="parent",
        targetEntity= Child.class,
        fetch = FetchType.LAZY,
        cascade= CascadeType.ALL,
        orphanRemoval=true)
   List<Child> children;
}

public class Child{
   @ManyToOne(
        targetEntity=Cotizacion.class,
        optional=false,
        fetch=FetchType.LAZY
        )
   @JoinColumn(
        name = "ID_PARENT",
        nullable = false
        ) 
   private Parent parent;   
}

Now in the client side i'm using GWT editor framework to edit the whole parent object, i mean.

Editor<ParentProxy>
ListEditor<List<ChildProxy>>

I have the requirement to edit the whole object on the same editor, so if i update a Child from the Parent and then flush() the driver the changes are propagated correctly.

The problem. On the server side i get the Parent with the children collection as persistedbag as null. (the Locator find() method is called for every Children). So if i do a change in the client side that is not propagated to the server side into the data base.

Note 1.- I check the whole object on the client side and the changes were made by the editor driver.

Note 2.- I tryed to retreive the whole object on the find() method of the Locator and doesn't work.

Note 3.- If i send the list as other parameter in my RequestContext and then update every child on the server side (DAO) it updates them correctly.

UPDATE: if i add a null to the children i get the whole list on server side instead of the persistedbag and the the update on the Child ocurrs.

Ex. parent.getChilds().add(null);

How RequestFactory makes the delta changes on the entities?

Any help would be apreciated.

UPDATE 2:solution of thomas.

The classes (listeners):

 public class HibernateUtil implements ServletContextListener {}
 public class AppSessionManager implements Filter {}

The line that hibernate needs:

 <property name="current_session_context_class">thread</property>

The web.xml config:

 <!-- Servlet context listerner  -->
<listener>
  <listener-class>xxx.yyy.server.tools.HibernateUtil</listener-class>
</listener>

<!-- Servlet for filter -->
<filter>  
    <filter-name>HibernateFilter</filter-name>  
    <filter-class>xxx.yyy.server.tools.AppSessionManager</filter-class>  
</filter>  

<filter-mapping>  
    <filter-name>HibernateFilter</filter-name>  
    <url-pattern>/gwtRequest</url-pattern>  
</filter-mapping> 

the entity locator:

public class BaseEntityLocator extends Locator<BaseEntity, Integer> {
/* 
 * Method to fetch an object and merge the updates
 * 
 * @see com.google.web.bindery.requestfactory.shared.Locator#find(java.lang.Class, java.lang.Object)
 */
@Override
public BaseEntity find(Class<? extends BaseEntity> clazz, Integer id) {
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();

    try {

        BaseEntity baseEntity = (BaseEntity) session.get(clazz, id);

        return baseEntity;
    } catch (RuntimeException e) {

        throw e;
    } 
 }
     ...
  }

Result? no more LazyInitializationException and other problems updating relations of type one to many. Hope this helps some one else.

¿Fue útil?

Solución

So you're changing a Child but don't touch the Parent (at least not its children property). RequestFactory will then send a diff for that Child only, and only send the IDs of the Parent and the other edited Child objects.

On the server-side, each received entity is loaded using its Locator, and then the diffs are applied. RequestFactory doesn't nothing re. the relations, so the Child that gets loaded by the Locator must be the same instance as the Child that gets loaded by the Parent Locator in its children property.

To achieve that, it's generally only necessary to use the session-per-request pattern (aka open session in view):

  • use a single session for the whole HTTP request to guarantee that the same entity will be the same Java instance
  • but use one transaction per service method (you shouldn't need a transaction in your locators) to guarantee that onSuccess on the client-side is meaningful.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top