在我的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>
那么,我错过了什么?
提前致谢并致以最诚挚的问候 帕斯卡
答案 0 :(得分:1)
我的第一个猜测是你在内存中缓存了与数据库不一致的数据。
确保在执行批量删除后清除以下2个缓存。缓存中的任何/所有数据都可能与DB不一致:
entityManager.clear();
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驱动程序缓存数据。这取决于您的提供商和配置。
运气好吗? =: - )
答案 1 :(得分:0)
EntityManager
的范围是持久性上下文,您可以使用entityManager.clear()
。
clear() : Clear the persistence context, causing all managed entities to become detached
否则,您可以在处理后关闭EntityManager
&amp;每次创建一个新的,这不是开销。
如果正在缓存,您可以尝试entityManager.getEntityManagerFactory().getCache().evictAll();