Gre*_*tle 8 java junit spring hibernate
我将 Hibernate 3.5.6-Final 与用于生产的 Oracle 数据库和用于集成测试的 H2 数据库一起使用。ID 创建的 Hibernate 映射看起来像这样,每个实体都扩展了 EasyPersistentObject:
@MappedSuperclass
public class EasyPersistentObject implements Serializable {
@Id
@SequenceGenerator(name = "hibernate_seq", sequenceName = "hibernate_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hibernate_seq")
protected Integer id;
Run Code Online (Sandbox Code Playgroud)
在每次 JUnit 集成测试之前,我都会从数据库中删除所有数据
new SchemaExport(configuration).create(false, true);
Run Code Online (Sandbox Code Playgroud)
一切正常,直到我为序列生成增加了 allocationSize。将其提高到例如 10 将在插入测试数据时使用 UniqueKeyConstraintViolations 破坏多个测试。
例如:
所以我的问题是:有没有办法在每次测试之前重置 Hibernates 分配的 ID?
另外: 我没有使用 JPA 中的 PersistenceManager,而是使用纯 Hibernate SessionFactory,它是这样创建的:
@Bean(name = "easySF")
public SessionFactory easySessionFactory(@Qualifier("easyConfig") AnnotationConfiguration configuration) {
configuration.setInterceptor(new HibernateInterceptor());
return configuration.buildSessionFactory();
}
@Bean(name = "easyConfig")
protected AnnotationConfiguration easyHibernateConfiguration() {
AnnotationConfiguration configuration = new AnnotationConfiguration();
configuration.setProperties(createHibernateProperties());
for (Class annotatedClass : getAnnotatedClasses()) {
configuration.addAnnotatedClass(annotatedClass);
}
return configuration;
}
Run Code Online (Sandbox Code Playgroud)
我真的需要重新加载整个 Spring 上下文才能重置 Hibernate ID 生成器吗?
也许解决方案之一是在新的 sessionfactory 中运行每个 JUNIT 测试。@Before所以使用和打开和关闭会话工厂@After
优点
缺点
更新
根据注释,另一种方法是在 @Before 方法中的每个 JUNIT 测试中重置序列
ALTER SEQUENCE Test.sequence RESTART WITH 1
Run Code Online (Sandbox Code Playgroud)
我面临着同样的问题,但没有找到内置的方法来做到这一点。我们使用的是 hibernate 4.2.7。
在深入调试休眠状态后,我最终扩展了序列生成器。我们使用标准序列生成器创建实体:
@SequenceGenerator(name = "SomeSeq", sequenceName = "DB_SEQ", allocationSize = 50)
Run Code Online (Sandbox Code Playgroud)
Hibernate 为每个实体创建一个 org.hibernate.id.SequenceHiLoGenerator。SequnceHiLoGenerator 委托给 OptimizerFactory.LegacyHiLoAlgorithmOptimizer 实例。
为了重置序列计数器并强制与数据库序列同步,您必须重置 LegacyHiLoAlgorithmOptimizer 中的内部变量。不幸的是,这些变量是私有的并且不可修改。我试图找到一种使用继承的方法,但没有找到一个优雅的解决方案。最后,我
创建了 SequenceHiLoGenerator 的源副本,并通过简单的重置功能对其进行了扩展:
public class ResetableIdGenerator extends SequenceGenerator {
public static int cycle = 0; // global, indicating current test cycle
protected int startingCycle = 0; // instance, indicating the test cycle the LegacyHiLoAlgorithmOptimizer was used the last time
[...]
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
// create a new HiLoOptimizer if there's a new test cycle
if (startingCycle < cycle) {
hiloOptimizer = new OptimizerFactory.LegacyHiLoAlgorithmOptimizer(getIdentifierType().getReturnedClass(),
maxLo);
startingCycle = cycle;
}
[....]
Run Code Online (Sandbox Code Playgroud)
修改实体以使用自定义生成器:
@GenericGenerator(name = "SomeSeq", strategy = "yourpackage.ResetableIdGenerator", parameters = {
@Parameter(name = "sequence", value = "DB_SEQ"), @Parameter(name = "max_lo", value = "49") })
Run Code Online (Sandbox Code Playgroud)
在测试之间重置序列生成器(@before 或 @after):
// reset Hibernate Sequences
ResetableIdGenerator.cycle++;
Run Code Online (Sandbox Code Playgroud)
我知道这不是一个好的解决方案 - 这是一个 hack。但它确实有效,也许有助于找到更好的解决方案。
编辑20170504:我最初的帖子包含一个错误:参数“sequenceName”和“allocationSize”是JPA参数。GenericGenerator 来自 hibernate。您必须使用“sequence”而不是“sequenceName”,您必须使用“max_lo”而不是“allocationSize”并将其设置为allocationSize-1。我更新了代码示例。对不起!
| 归档时间: |
|
| 查看次数: |
17801 次 |
| 最近记录: |