web-dev-qa-db-ja.com

Spring JpaRepository-エンティティの接続解除と接続

私はスプリングブートを使用し、JPAで休止状態にします。 JpaRepositoryインターフェースを使用して、リポジトリーを実装しています。次のUserRepositoryと同様

public interface UserRepository extends JpaRepository<User, Long> {
}

フォローを達成したい

  1. ユーザーエンティティを読み込みます。
  2. エンティティオブジェクトの状態を変更します。 user.setName( "foo")
  3. 外部システムのWebサービス呼び出しを実行します。呼び出し結果をDBに保存します
  4. このWebサービス呼び出しの応答が成功した場合にのみ、ユーザーの新しい状態をリポジトリに保存します。

上記のすべてのステップが1つのトランザクションで発生しているわけではありません。つまり、外部サービスコールはトランザクション外です。

Webサービスの結果をリポジトリ経由でDBに保存すると、ユーザーエンティティの変更も保存されます。私の理解では、これはステップ3の永続コンテキストのアンダーレイのフラッシュによるものです。Googleをいくつか試した後、ステップ1でユーザーエンティティをデタッチし、ステップ4で再アタッチできれば、目的を達成できると思います。私の理解が正しい場合、どのようにこれを達成できますか? JpaRepositoryインターフェースには、エンティティを切り離す方法はありません。

以下は説明するコードです

public void updateUser(int id, String name, int changeReqId){
    User mUser = userRepository.findOne(id); //1
    mUser.setName(name); //2

    ChangeRequest cr = changeRequestRepository.findOne(changeReqId);
    ChangeResponse rs = userWebService.updateDetails(mUser); //3

    if(rs.isAccepted()){
        userRepository.saveAndFlush(mUser); //4
    }

    cr.setResponseCode(rs.getCode());
    changeRequestRepository.saveAndFlush(cr); //this call also saves the changes at step 2
}

ありがとう

22
amique

JPA 2.0を使用している場合、 EntityManager#detach() を使用して、永続コンテキストから単一のエンティティを切り離すことができます。また、Hibernateには Session#evict() があり、これは同じ目的を果たします。

JpaRepositoryはこの機能自体を提供しないため、 カスタム実装を追加 に追加できます。

_public interface UserRepositoryCustom {
    ...
   void detachUser(User u);
    ...
}

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
    ...
}

@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
    ...
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void detachUser(User u) {
        entityManager.detach(u);
    }
    ...
}
_

私はこのコードを試したことはありませんが、動作させることができるはずです。 _@PersistenceContext_を使用して、サービスクラス(updateUser()が存在する)でEntityManagerを保持し、カスタム実装をリポジトリに追加する手間を省くこともできます。

47
Predrag Maric

entityManager.clear()はすべてのJPAオブジェクトを切断するため、接続を維持する予定の他のオブジェクトがある場合、これはすべての場合に適切なソリューションではない可能性があります。

クリア

_/**
 * Clear the persistence context, causing all managed
 * entities to become detached. Changes made to entities that
 * have not been flushed to the database will not be
 * persisted.
 */
public void clear();
_

entityManager.detach(entity);指定されたエンティティを永続コンテキストから削除します

デタッチ

_/**
 * Remove the given entity from the persistence context, causing
 * a managed entity to become detached.  Unflushed changes made
 * to the entity if any (including removal of the entity),
 * will not be synchronized to the database.  Entities which
 * previously referenced the detached entity will continue to
 * reference it.
 * @param entity  entity instance
 * @throws IllegalArgumentException if the instance is not an
 *         entity
 * @since Java Persistence 2.0
 */
public void detach(Object entity);
_
4
Xstian