59

EntityManager を通じて取得した特定の JPA エンティティ Bean をデタッチする最も簡単な方法は何でしょうか。または、最初に分離されたオブジェクトを返すクエリを作成して、それらが本質的に「読み取り専用」として機能するようにすることはできますか?

私がこれをしたい理由は、Bean 内のデータを変更したいからです - 私のアプリケーションでのみ使用しますが、データベースに永続化することはありません。私のプログラムでは、最終的に EntityManager で flush() を呼び出す必要があります。これにより、接続されたエンティティから基になるデータベースへのすべての変更が保持されますが、特定のオブジェクトを除外したいと考えています。

4

15 に答える 15

62

(答えるには遅すぎるかもしれませんが、他の人には役立つ可能性があります)

現在、JPAを使用して最初のシステムを開発しています。残念ながら、このシステムがほぼ完成すると、この問題に直面します。

簡単に言えば。Hibernateを使用するか、JPA2.0を待ちます。

Hibernateでは、「session.evict(object)」を使用してセッションから1つのオブジェクトを削除できます。JPA 2.0では、現在ドラフトに、永続コンテキストから1つのオブジェクトをデタッチするための「EntityManager.detach(object)」メソッドがあります。

于 2009-05-22T14:04:49.333 に答える
29

どの JPA 実装を使用しentityManager.detach(object)ても、JPA 2.0 と JEE6 の一部になっているので、そのまま使用してください。

于 2012-08-27T10:04:23.153 に答える
19

EntityManager からオブジェクトをデタッチする必要があり、基になる ORM レイヤーとして Hibernate を使用している場合は、Hibernate Sessionオブジェクトにアクセスして、 Mauricio Kanada が前述したSession.evict(Object)メソッドを使用できます。

public void detach(Object entity) {
    org.hibernate.Session session = (Session) entityManager.getDelegate();
    session.evict(entity);
}

もちろん、別の ORM プロバイダーに切り替えた場合、これは機能しなくなりますが、ディープ コピーを作成することが望ましいと思います。

于 2010-01-12T14:10:22.360 に答える
17

残念ながら、現在の JPA 実装である AFAIR では、1 つのオブジェクトをエンティティーマネージャーから切断する方法はありません。

EntityManager.clear() はすべての JPA オブジェクトを切断するため、接続を維持する予定の他のオブジェクトがある場合、すべてのケースで適切な解決策ではない可能性があります。

したがって、最善の策は、オブジェクトを複製し、その複製をオブジェクトを変更するコードに渡すことです。プリミティブで不変のオブジェクト フィールドは、デフォルトのクローン メカニズムによって適切な方法で処理されるため、多くの配管コードを記述する必要はありません (集約された構造体をディープ クローンすることを除けば)。

于 2008-08-28T18:39:55.213 に答える
3

私の知る限り、それを行う唯一の直接的な方法は次のとおりです。

  1. txnをコミットする-おそらく合理的なオプションではない
  2. 永続コンテキストをクリアします-EntityManager.clear()-これは残酷ですが、クリアします
  3. オブジェクトをコピーする-ほとんどの場合、JPAオブジェクトはシリアライズ可能であるため、これは簡単です(特に効率的ではない場合)。
于 2008-08-28T01:45:09.240 に答える
3

使用する場合EclipseLinkは、オプションもあります。

クエリ ヒントを使用しeclipselink.maintain-cache"="falseます。返されたすべてのオブジェクトが切り離されます。

API を使用してEclipseLink JpaEntityManager copy()、オブジェクトを目的の深さにコピーします。

于 2011-03-31T13:16:31.087 に答える
1

これは迅速で汚いですが、オブジェクトをシリアル化および逆シリアル化することもできます。

于 2009-10-22T07:59:10.463 に答える
1

Bean にあまり多くのプロパティがない場合は、新しいインスタンスを作成し、永続化された Bean からそのすべてのプロパティを手動で設定するだけです。

これは、コピー コンストラクターとして実装できます。たとえば、次のようになります。

public Thing(Thing oldBean) {
  this.setPropertyOne(oldBean.getPropertyOne());
  // and so on
}

それで:

Thing newBean = new Thing(oldBean);
于 2008-08-28T02:36:16.857 に答える
1

私は SEAM と JPA 1.0 を使用しており、システムにはすべてのフィールドの変更をログに記録する必要がある機能があるため、エンティティの同じフィールドをログに記録する必要がある場合は、値オブジェクトまたはデータ転送オブジェクトを作成しました。新しい pojo のコンストラクターは次のとおりです。

    public DocumentoAntigoDTO(Documento documentoAtual) {
    Method[] metodosDocumento = Documento.class.getMethods();
    for(Method metodo:metodosDocumento){
        if(metodo.getName().contains("get")){
            try {
                Object resultadoInvoke = metodo.invoke(documentoAtual,null);
                Method[] metodosDocumentoAntigo = DocumentoAntigoDTO.class.getMethods();
                for(Method metodoAntigo : metodosDocumentoAntigo){
                    String metodSetName = "set" + metodo.getName().substring(3);
                    if(metodoAntigo.getName().equals(metodSetName)){
                        metodoAntigo.invoke(this, resultadoInvoke);
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2011-03-30T20:12:58.903 に答える
1

次のように永続的なエンティティ オブジェクトを拡張する DTO オブジェクトを作成した同様のケースに対処してください。

class MyEntity
{
   public static class MyEntityDO extends MyEntity {}

}

最後に、スカラー クエリは、目的の管理されていない属性を取得します。

(Hibernate) select p.id, p.name from MyEntity P
(JPA)       select new MyEntity(p.id, p.name) from myEntity P
于 2014-09-03T16:16:55.440 に答える
0

実際にリモート境界を越えてエンティティを渡したいためにここにたどり着いた場合は、休止状態をだますためのコードをいくつか挿入するだけです。

for(RssItem i : result.getChannel().getItem()){
}

Cloneable は、PersistantBag を実際にコピーするため、機能しません。

また、シリアル化可能なバイト配列ストリームとパイプ ストリームの使用については忘れてください。デッドロックを回避するためにスレッドを作成すると、概念全体が失われます。

于 2011-05-27T08:57:32.997 に答える
-1

エンティティの主キーが変更されていない場合は、メソッド EntityManager.refresh(Object o) も使用できると思います。このメソッドは、エンティティの元の状態を復元します。

于 2009-11-27T12:21:53.577 に答える