0

我有以下代码:

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;   
}

现在在客户端,我正在使用 GWT 编辑器框架来编辑整个父对象,我的意思是。

Editor<ParentProxy>
ListEditor<List<ChildProxy>>

我需要在同一个编辑器上编辑整个对象,所以如果我从父级更新一个子级,然后刷新()驱动程序,则更改会正确传播。

问题。在服务器端,我将 Parent 与 children 集合作为 persistedbag 为 null。(为每个孩子调用 Locator find() 方法)。因此,如果我在客户端进行更改,但不会传播到服务器端到数据库中。

注意 1.- 我在客户端检查了整个对象,并且更改是由编辑器驱动程序进行的。

注意 2.- 我试图在 Locator 的 find() 方法上检索整个对象,但不起作用。

注意 3.- 如果我将列表作为 RequestContext 中的其他参数发送,然后更新服务器端 (DAO) 上的每个子节点,它会正确更新它们。

更新:如果我给孩子添加一个空值,我会在服务器端获得整个列表,而不是持久化包和孩子的更新。

前任。parent.getChilds().add(null);

RequestFactory 如何对实体进行增量更改?

任何帮助将不胜感激。

更新2:托马斯的解决方案。

类(听众):

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

休眠需要的行:

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

web.xml 配置:

 <!-- 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> 

实体定位器:

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;
    } 
 }
     ...
  }

结果?不再有 LazyInitializationException 和其他更新一对多类型关系的问题。希望这对其他人有帮助。

4

1 回答 1

0

因此,您正在更改 aChild但不要触摸Parent(至少不是它的children属性)。然后,RequestFactory 将仅发送一个差异Child,并且仅发送该对象Parent和其他已编辑Child对象的 ID。

在服务器端,每个接收到的实体都使用它的 加载Locator,然后应用差异。RequestFactory 什么都不是。关系,因此由Child加载的Locator 必须与其属性中Child由 加载的 相同的实例。Parent Locatorchildren

为了实现这一点,通常只需要使用session-per-request模式(又名open session in view):

  • 对整个 HTTP 请求使用单个会话,以保证同一个实体是同一个 Java 实例
  • 但是每个服务方法使用一个事务(你不应该在你的定位器中需要一个事务)来保证onSuccess在客户端是有意义的。
于 2013-09-12T10:16:59.043 回答