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

同じエディターでオブジェクト全体を編集する必要があるため、親から子を更新してからドライバーを flush() すると、変更が正しく反映されます。

問題。サーバー側では、null として永続化されたバッグとして子コレクションを持つ親を取得します。(すべての子に対して Locator find() メソッドが呼び出されます)。したがって、クライアント側で変更を行った場合、サーバー側に伝播されずにデータベースに反映されます。

注 1.- クライアント側でオブジェクト全体をチェックすると、変更はエディター ドライバーによって行われました。

注 2.- Locator の find() メソッドでオブジェクト全体を取得しようとしましたが、機能しません。

注 3.- リストを RequestContext の他のパラメーターとして送信し、サーバー側 (DAO) ですべての子を更新すると、正しく更新されます。

更新:子に null を追加すると、persistedbag の代わりにサーバー側でリスト全体が取得され、子の更新が発生します。

元。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 や、タイプ 1 対多のリレーションを更新するその他の問題はもうありません。これが他の人に役立つことを願っています。

4

1 に答える 1

0

したがって、 a を変更してChildいますが、に触れないでくださいParent(少なくともそのchildrenプロパティには触れないでください)。RequestFactory は、その diffChildのみを送信し、Parentおよびその他の編集済みChildオブジェクトの ID のみを送信します。

サーバー側では、受信した各エンティティがその を使用して読み込まれLocator、差分が適用されます。RequestFactory は何もしません。したがって、Childによってロードされる は、 によってそのプロパティにロードされると同じインスタンスであるLocator 必要があります。ChildParent Locatorchildren

これを実現するには、通常、セッションごとのリクエストパターン (別名open session in view )を使用するだけで済みます。

  • HTTP 要求全体に対して 1 つのセッションを使用して、同じエンティティが同じ Java インスタンスになることを保証します。
  • ただし、サービス メソッドごとに 1 つのトランザクションを使用して (ロケーターにトランザクションは必要ありません) onSuccess、クライアント側で意味があることを保証します。
于 2013-09-12T10:16:59.043 に答える