【问题标题】:How to update the collection of @onetomany relationship如何更新@onetomany 关系的集合
【发布时间】:2013-09-13 23:28:26
【问题描述】:

我有以下代码:

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) 上的每个子节点,它会正确更新它们。

更新:如果我向子项添加 null,我会在服务器端获得整个列表,而不是持久化包和子项上的更新。

例如。 parent.getChilds().add(null);

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

我们将不胜感激。

更新 2:thomas 的解决方案。

类(监听器):

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

hibernate需要的行:

 <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 和其他更新一对多类型关系的问题。希望这对其他人有帮助。

【问题讨论】:

    标签: hibernate gwt requestfactory


    【解决方案1】:

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

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

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

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    相关资源
    最近更新 更多