我有一个带有TableGenerator和allocationSize=25的JPA实体。如果我要手动更新TableGenerator表并为下一个ID开始范围给它一个新的值,那么在当前范围通过之前,它不会有效果。
例如,如果当前的TableGenerator表值为10,我将开始获取实体ID为250、251、252等。在255时,我将TableGenerater表值更改为20。然而,下一个ID仍然是256,257,一直到274,那么下一个ID将是500个。
当然,这是很自然的--但我想知道,是否有办法告诉Hibernate,暂时忽略当前的间隔,开始从TableGenerator表中的任何内容分配is?
所以,为了回答为什么,在我的特殊情况下:
我正在为我的团队的产品开发一个测试自动化工具,它能够通过运行的系统(使用客户端应用程序、API等)来设置测试数据。定义了测试数据配置(让我们将它们称为testdatas),以便将多个测试数据一起用于特定的测试用例/测试套件。
现在,一旦运行了一个testdata,该工具就会将输入的数据从db提取到SQL语句中,并将它们保存到文件中。这有几个原因,但主要是关于性能的--如果我想使用特定的测试数据运行100个测试用例,我只关心“手动”插入一次的测试数据,然后每次重置时,我可能会采用更快的方法将测试数据直接插入数据库。
但是,正如我所说的,可以同时使用多个测试数据。如果testdata01和testdata02都影响相同的表,怎么办?提取的SQL语句不会只包含该特定测试数据的数据,如果另一个测试数据已经预先运行。
对此,一个简单的解决方案是为每个测试数据保留一个ID间隔。对于每个表,testdata01有间隔[10000,20000),testdata02有间隔[20000,30000)等等。这很容易实现--在运行每个testdata之前,只需将所有TableGenerator表更新到testdata的ID间隔的下界--然后,在运行testdata设置之后,只提取间隔内带有ID的行。
这非常有用,并且确保在testdatas之间的in中不会有任何冲突,并且每个testdata的导出SQL只包含该特定测试数据的数据,而不管数据库中可能还有什么数据。然而,在allocationSize不是1的情况下,条目可能仍然出现在给定实体的保留ID间隔之外,尽管我们已经更新了该实体的TableGenerator。
因此,简而言之,我想做的是,在更新TableGenerator表之后,在开始运行测试数据设置之前,我想告诉Hibernate,对于每个实体,下次生成ID时,不要考虑从TableGenerator的范围中生成的下一个值,而是检查数据库中的TableGenerator表,以便使用next。
发布于 2013-08-16 14:20:08
所以我自己设法抓到了这个。如果任何人有同样的需要,可供今后参考:
public void moveToNextInterval(Class entity, javax.persistence.EntityManager em) throws IllegalAccessException, InstantiationException {
javax.persistence.TableGenerator tableGenerator = null;
for (Method method : entity.getMethods()) {
tableGenerator = method.getAnnotation(javax.persistence.TableGenerator.class);
if (tableGenerator != null) {
break;
}
}
if (tableGenerator != null && tableGenerator.allocationSize() > 1) {
int allocationSize = tableGenerator.allocationSize();
org.hibernate.impl.SessionImpl session = (org.hibernate.impl.SessionImpl) em.unwrap(org.hibernate.Session.class);
IdentifierGenerator idGenerator = session.getFactory().getIdentifierGenerator(entity.getName());
while ((Long)idGenerator.generate(session, entity.newInstance()) % allocationSize != allocationSize - 1);
}
}还不太习惯Hibernate或JPA,所以可能会有很多改进。将其推广到任何类型的序列生成器都不会太困难。此外,您可能只需创建一个实体实例并重用它。此外,我猜会有超出预期ID的风险;例如,如果allocationSize=25和最后一个ID是24,我们已经更新了TableGenerator表并将其设置为10,那么调用该方法实际上会使其变为275,而不是250个。对我来说已经够好了,但很高兴知道。
https://stackoverflow.com/questions/18206688
复制相似问题