Hibernate与JPA 1.0缓存问题

时间:2014-02-24 21:04:47

标签: java spring hibernate caching jpa

我似乎有一个清除hibernate缓存的问题,无论我尝试清除任何缓存,如果我调用我的DAO.findAll(),我仍然会得到几个结果。所有这些都不再存在于我的本地数据库中。一些结果已经存在数周,但仍然以某种方式出现。这让我疯了几天,我已经搜索了很多东西,看看能不能找到我还没试过的东西。所以这是我的基本设置

  • hibernate core 3.3
  • hibernate annotations 3.4
  • hibernate commons annotations 3.4
  • spring 3.0.7
  • persistance api 1.0
  • junit 4.8.2

我现在没有更新版本的选项,因此我需要在当前版本堆栈中找到解决方案。一切都在使用设置,但是为了测试我的DAO我似乎无法清除一些旧的缓存。这就像它从某个地方的平面文件中读取而不会消失! lol .. grrrr ...我希望有人能看到明显的答案或引导我朝着正确的方向前进..我知道下面的代码示例不是完全100%的课程,但我已经拿出了我认为最多的与此问题相关,如果需要更多帮助澄清,请知道!

只是一点点背景,我一直在玩Junit测试来更新查询,但我发现我得到了缓存结果,而不是我实际查询的结果,所以从那以后我一直试图找出一些我可以清除这个臭名昭着的缓存的方式,这里有一些我已经进一步查看的链接,但到目前为止它似乎没有处理第一级和第二级缓存..

我检查的剩余链接列表需要更多声望点.. :(

我所看到的很多内容都是针对JPA 2和/或休眠本身。但是对于带有休眠的JPA 1来说并不是太多..我认为问题的一部分是如果你看下面我的junit测试设置,我注释掉了complete()方法,它将回滚任何插入作为测试的一部分,我想允许数据保留在数据库中,所以我评论了这一点,但似乎我孤立了会话或其他东西,现在我无法删除那些缓存的记录,即使我手动删除了数据库中的原始条目。

这基本上就是我的目标...

持久性xml

<persistence-unit name="ServicePersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

<class>com.pkg.service.model.MyService</class>

    <properties>
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="validate"/>
        <property name="hibernate.connection.username" value="xxxx"/>
        <property name="hibernate.connection.password" value="xxxx"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.connection.autocommit" value="false"/>
    </properties>
</persistence-unit>

Context XML

<context:component-scan base-package="com.pkg.service.dao" />
<context:annotation-config/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="META-INF/jpa-persistence.xml" />
    <property name="persistenceUnitName" value="ServicePersistenceUnit" />
</bean>

<bean id="entityManager" class="javax.persistence.EntityManager" factory-bean="entityManagerFactory" factory-method="createEntityManager" />

<bean id="ServiceDaoImpl" class="com.pkg.service.dao.impl.ServiceDaoImpl">
    <property name="entityManager" ref="entityManager"/>
</bean>

ServiceDAOImpl

@Repository("serviceDao")
public class ServiceDaoImpl extends AbstractJpaDAO<String, StoredService> implements ServiceDao {

@Autowired
EntityManagerFactory entityManagerFactory;

@PostConstruct
public void init() {
    super.setEntityManagerFactory(entityManagerFactory);
}

public EntityManagerFactory getEntityManagerFactory() {
    return entityManagerFactory;
}

@Override
@Transactional
public void save(StoredService storedService) {
    getJpaTemplate().persist(storedService);
}

@Override
@Transactional(readOnly = true)
public Collection<MyService> findServices(final QueryParams queryParams) throws IllegalArgumentException {
    List<MyService> result = getJpaTemplate().execute(new JpaCallback<List<MyService>>() {
    @Override
    @SuppressWarnings("unchecked")
        public List<MyService> doInJpa(final EntityManager em) throws PersistenceException {
            Query query = ServiceQueryFactory.createQueryWithParams(queryParams, em); 
            return query.getResultList();
        }
    });
    return result;
}

}

MyService(Model Obj)

@Entity
@Table(name = "MYSERVICE")
@SqlResultSetMapping(
    name = ServiceQueryHelper.MY_SERVICE_MAPPING, 
    entities = { 
        @EntityResult(
            entityClass = com.pkg.service.model.MyService.class, 
            fields = {
                @FieldResult(name = "id",       column = "id"), 
                @FieldResult(name = "serviceName",  column = "servicename"),
                @FieldResult(name = "serviceId",    column = "serviceid")
            }
        ) 
    }
)
public class MyService implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(
        name = "MYSERVICE_SEQ", 
        sequenceName = "MYSERVICE_SEQ",   
        allocationSize = 1)
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE, 
        generator = "MYSERVICE_SEQ")
    private long id;

    private String serviceName;

    private long serviceId;

    //GETTERS AND SETTERS...

}

助手类

public class ServiceQueryHelper {

    public static final String MY_SERVICE_MAPPING = "my_service_mapping";
    public static final String MY_QUERY = "This is my select query";

}

public class ServiceQueryFactory {

    public static Query createQueryWithParams(QueryParams queryParams, EntityManager em){

        //QueryParams aren't used right now, working on clearing the cache first :)

        Query query = em.createNativeQuery(ServiceQueryHelper.MY_QUERY, ServiceQueryHelper.MY_SERVICE_MAPPING);
        return query;

    }

}

最后是测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/persistence-test.xml" })
public class ServiceDaoImplTest {

    @Resource
    private ServiceDaoImpl ServiceDaoImpl;

    @Resource(name = "entityManager")
    private EntityManager entityManager;


    @Before
    public void init() {
        serviceDaoImpl.setEntityManager(entityManager);
        entityManager.getTransaction().begin();
        //setupTestData();
    }   

    @After
    public void complete() {
        entityManager.flush();
        entityManager.getTransaction().rollback();
    }

    @Test
    public void shouldReturnNoServices() {

        //There are no services in the database right now...
        Collection<MyService> services = ServiceDaoImpl.findAll();

        //This fails with services that seem to be in cache
        assertEquals("Should be empty", 0, services.size());

    }

}

1 个答案:

答案 0 :(得分:0)

看起来很奇怪,事实证明我看到的问题是打开SQL Developer Lite的结果,并登录到我通过Junit测试的数据库。对于遇到类似问题的其他任何人,我首先注意到在运行一个查询时发生冲突,该查询将几个LAST_VALUE函数应用于基本上“角色化”数据,并且能够选择一个累积了我的记录的行感兴趣的。

我没有把这两者连接成最初的冲突,而是专注于看起来像是一个缓存问题,但无论我试图通过第一级,第二级和查询缓存清除缓存,我总是得到从数据库/ hibernate返回相同的“旧”结果,而不是我期望通过新查询看到的数据......奇怪的是,数据库中也没有任何数据。

我注意到的另一个奇怪的事情是,当我厌倦了运行本地查询以删除TableName以查看我是否能够以某种方式清除我看到的结果时,它只会坐下并挂起,好像它处于死锁中一样。我能想到的唯一可能导致冲突的是数据库工具并且可以查看该表。一旦我关闭了,我所有删除的尝试都被执行了,一旦我再次清除了实体管理器,我的问题就解决了。所以在一天结束的时候,当我试图在junit测试中操作数据时,我的SQL Developer工具正在打开。