【问题标题】:Easy way to truncate all tables, clear first and second level hibernate cache?截断所有表,清除一级和二级休眠缓存的简单方法?
【发布时间】:2010-06-25 22:04:59
【问题描述】:
我正在为我正在开发的 Spring/Hibernate 应用程序编写一些集成测试,我想在尽可能接近真实条件的情况下进行测试,其中包括使用 Hibernate 的二级缓存和提交事务。
我想知道是否有一种有效的方法可以让 Hibernate 从数据库和缓存中删除所有内容。我能想到的最好办法是对每种类型的对象使用 HQL“从 XImpl 删除”行,但我有几十个域对象,感觉应该有更好的方法。
【问题讨论】:
标签:
java
unit-testing
hibernate
orm
【解决方案1】:
对于数据库,使用SchemaExport 工具重新创建架构:
Configuration cfg = ....;
new SchemaExport(cfg).create(false, true);
对于二级缓存,从SessionFactory 获取对底层缓存区域的访问权并逐出所有内容:
SessionFactory sf = ...;
Cache cache = sf.getCache();
cache.evictEntityRegions();
cache.evictCollectionRegions();
cache.evictQueryRegions();
对于一级缓存,好吧,只需获取一个新的Session 或调用session.clear()。
【解决方案2】:
采用上面 Pascal 的方法,我开始寻找在 Spring 中创建 SchemaUpdate 对象的正确方法,并意识到我不需要这样做。相反,我可以为 Hibernate 获取 Spring 的 sessionFactory 对象并要求它删除/创建模式。将其与 Pascal 解决方案的其余部分相结合,我们得到:
LocalSessionFactoryBean localSessionFactoryBean = (LocalSessionFactoryBean)appContext.getBean("&sessionFactory");
localSessionFactoryBean.dropDatabaseSchema();
localSessionFactoryBean.createDatabaseSchema();
Cache cache = sf.getCache();
cache.evictEntityRegions();
cache.evictCollectionRegions();
cache.evictQueryRegions();
这很有效。唯一的缺点是(至少对我而言)它比在每个表名上调用“从 obj1 删除”、“从 obj2 删除”要慢得多。不过,我喜欢不必重复自己。
【解决方案3】:
看看Unitils。它对我们已经使用了一段时间的database testing(使用 DbUnit)提供了很好的支持。它非常灵活,因此如果您发现需要将数据预加载到数据库中以进行特定的单元测试,您可以使用它。
使用 Unitils,您将创建一个表示空数据库的数据集文件 (empty-db.xml):
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<obj1/>
<obj2/>
</dataset>
关于需要配置数据集的类或测试
@DataSet("empty-db.xml")
我们有一个用于所有持久性测试的通用基类,因此我们能够将注释放在一个地方。
不利的一面是,每次将实体添加到 Hibernate 时,都必须向该文件添加行。而且您必须获得正确的顺序才能与外键约束保持一致。我们最终添加了一个单元测试来检查这个文件是否符合 Hibernate 配置以保持检查。
好处是,特别是对于大型架构,它比重建架构要快得多。