0

Seam / Glassfish /JPAコンテナで次の操作を実行した後:

@ApplicationScoped
public class JpaGlossaryDataAccessObject implements IGlossaryDataAccessObject {
    // ...
    @Transactional
    public void deleteColumn(String glossaryName, String columnName) {
        final GlossaryColumn column = getColumn(glossaryName, columnName);
        entityManager.remove(column);
    }
    // ...
}

要求された列はDBから正常に削除されます。これは、SQLワークベンチを使用して確認できます。ただし、後で次のメソッドを呼び出す場合:

@ApplicationScoped
public class JpaGlossaryDataAccessObject implements IGlossaryDataAccessObject {
    // ...
    @Transactional
    public List<Glossary> getGlossaries(Collection<String> glossaryNames) {
        glossaryNames.retainAll(getGlossaryNames());
        return entityManager.createQuery(SELECT_ALL_NAMED_GLOSSARIES, Glossary.class).setParameter(GLOSSARY_NAMES_PARAMETER_INDEX, glossaryNames).getResultList();
    }
    // ...
}

これは基本的に前述の列を含む用語集を返しますが、削除された列はまだ用語集オブジェクトにあります。それらはデータベースにもう存在していませんが。どうすればいいの?これを機能させるために実行する必要のある追加の更新はありますか?

ちなみに、私のbeans.xmlは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="urn:java:ee"
    xmlns:security="urn:java:org.jboss.seam.security" xmlns:permission="urn:java:org.jboss.seam.security.permission"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd">
    <alternatives />
    <decorators />
    <interceptors>
        <class>org.jboss.seam.security.SecurityInterceptor</class>
        <class>org.jboss.seam.transaction.TransactionInterceptor</class>
    </interceptors>
    <security:IdentityImpl>
        <s:modifies />
        <security:authenticatorClass>ch.diction.webportal.security.seam.authentication.ChallengeResponseIdmAuthenticatorDecorator
        </security:authenticatorClass>
    </security:IdentityImpl>
</beans>

だから、私は何が欠けていますか?

よろしくお願いしますPascal

4

2 に答える 2

1

私の最初の推測は、DBと矛盾するメモリにデータをキャッシュしたことです。

一括削除を行った後は、必ず次の2つのキャッシュをクリアしてください。キャッシュ内のすべてのデータがDBと矛盾している可能性があります。

  • EntityManagerキャッシュ(つまり、永続コンテキスト): entityManager.clear();
  • EntityManagerFactoryキャッシュ(つまり、レベル2キャッシュ):
    entityManager.getCache().evictAll();
    または entityManagerFactory.getCache.evictAll();

理論的には(実際にはではありませんが)、キャッシュ内のすべてのオブジェクトを更新することは可能です。

HashMap props = new HashMap();
// Semantically, refresh already bypasses the second level cache, no hint required. 
// But this hint says to then store the refreshed value back in the second level cache:
props.put("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);
em.refresh(ent, props);

しかし、それは本当に面倒であり、利益をもたらさないでしょう。まず、キャッシュに保存されているすべてのエンティティをどのように繰り返しますか?次に、上記の単一の呼び出しでそれらを削除した場合、必要に応じて更新された状態で自動的に再ロードされます。

JDBCドライバーがデータをキャッシュしている可能性もあります。これは、プロバイダーと構成によって異なります。

これで運がいいですか?= :-)

于 2012-10-15T08:50:21.653 に答える
0

のスコープEntityManagerは永続コンテキストであり、を使用できますentityManager.clear()

clear() : Clear the persistence context, causing all managed entities to become detached

それ以外の場合は、後処理を閉じて、EntityManager毎回新しいものを作成できます。これはオーバーヘッドではありません。

キャッシュされている場合は、試すことができますentityManager.getEntityManagerFactory().getCache().evictAll();

于 2012-10-15T08:13:19.207 に答える