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);
    }
    // ...
}

请求的列已成功从数据库中删除,我可以使用 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>

那么,我错过了什么?

在此先感谢和最好的问候帕斯卡

4

2 回答 2

1

我的第一个猜测是您在内存中缓存了与数据库不一致的数据。

确保在进行批量删除后清除以下 2 个缓存。缓存中的任何/所有数据都可能与数据库不一致:

  • EntityManager 缓存(即持久化上下文): entityManager.clear();
  • EntityManagerFactory 缓存(即二级缓存):
    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 回答