如何更新@onetomany关系的集合

时间:2013-09-11 18:10:50

标签: hibernate gwt requestfactory

我有以下代码:

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更新一个Child,然后flush()驱动程序,那么更改会正确传播。

问题所在。在服务器端,我将带有子集合的Parent作为persistedbag获取为null。 (为每个Children调用Locator find()方法)。因此,如果我在客户端进行更改,而不是将其传播到服务器端进入数据库。

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

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

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

更新:如果我给孩子们添加一个null,我会在服务器端获取整个列表,而不是persistedbag和Child ocurrs上的更新。

实施例。 parent.getChilds()添加(空);

RequestFactory如何对实体进行delta更改?

任何帮助都会被贬低。

更新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以及更新类型1到多个关系的其他问题。希望这有助于其他人。

1 个答案:

答案 0 :(得分:0)

因此,您要更改Child但不要触及Parent(至少不是children属性)。然后,RequestFactory将仅为Child发送差异,并仅发送Parent和其他已编辑的Child对象的ID。

在服务器端,使用其Locator加载每个接收的实体,然后应用差异。 RequestFactory没有任何重要性。关系,因此Child 加载的Locator必须Child {Parent加载的Locator相同{1}} children属性中的{1}}。

要实现这一点,通常只需要使用会话每请求模式(在视图中开放会话):

  • 对整个HTTP请求使用单个会话,以保证同一实体将是相同的Java实例
  • 但是每个服务方法使用一个事务(您的定位器中不需要事务)以保证客户端的onSuccess有意义。