我正在为我一直在处理的持久层编写一些测试,但遇到了一个无法处理的异常,ConcurrentModificationException em> 它发生在 org.hibernate.mapping.Table.cleanseUniqueKeyMap(Table.java:291)
。
结果是这行代码:
final Map.Entry<String,UniqueKey> uniqueKeyEntry = uniqueKeyEntries.next();
经过一番研究后,我发现异常是由一个线程在迭代该集合时修改该集合引起的。话虽如此,我觉得我所做的任何事情都没有导致这种情况发生,有什么关于故障排除的建议吗?
顺便说一句,我正在使用 hibernate 4.1.5
。我不知道这是否能解决任何问题。这是我的测试:
@Test
public void testCreateMobsterUser() {
try {
final MobsterUserDAO test = new MobsterUserDAO(); //throws exception
//does stuff w/ return value...
如您所见,我们尝试初始化 dao 让我们看看该代码:
public MobsterUserDAO() {
super(MobsterUser.class);
}
好吧,这并没有向我们展示太多内容,所以让我们看看通用的 dao 构造函数,看看您是否发现了问题。
public MobsterBaseHibernateDAO(final Class<T> clazz) {
this.clazz = clazz;
//This next line is where the exception is actually occuring
final EntityManagerFactory factory = Persistence.createEntityManagerFactory("mobsterdb");
this.manager = (HibernateEntityManager) factory.createEntityManager();
}
现在我不确定 Persistance.createEntityManagerFactory 是什么样的兔子洞,但这是在异常发生之前执行的代码的最后一行。
最佳答案
当您在 for-each 循环中迭代集合并在其他地方更改集合时,就会发生并发修改。常见的解决方案之一是使用 Iterator 而不是 for-each 循环。或者让您的集合处于synchronized
block 中。
到处都有关于它的资源:
Avoiding ConcurrentModificationException ,它说:
您可以将列表转换为数组,然后迭代该数组。这种方法适用于中小型列表,但如果列表很大,则会对性能产生很大影响。
您可以通过将列表放入同步块(synchronized block)中来在迭代时锁定列表。不推荐这种方法,因为它会停止多线程的好处。
如果您使用的是 JDK1.5 或更高版本,则可以使用 ConcurrentHashMap 和 CopyOnWriteArrayList 类。这是推荐的方法。
另外:
Concurrent Modification exception
How to debug ConcurrentModificationException?
关于java - Hibernate 抛出 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11534424/