我一直在努力解决这个问题了几天,我不能完全发现,我很高兴与解决方案持续对象时。我可以通过不同程度的间接方式解决它,但这似乎是我应该能够做的事情,而我发现其他一些人可能有我的问题,但他们中的任何一个似乎都没有确切的问题或没有提供答案。遭遇数据库死锁与JPA使用持续引用
虽然我这样做过成功使用Hibernate,我一直没能得到它与JPA,这是我专注于现在所做的工作。
初步信息:使用所述持续扩展
- 吉斯3.0应用,休眠(W /注释),和C3P0(带有至多5个连接)。我们正在从提供者注入EntityManager,并且我可以确认EntityManager对象与整个此过程中的事务对象保持相同。
- 作为Web应用程序的一部分设计,目前的问题只发生在使用JUnit和dbUnit的自动化集成测试中。访问是针对单例对象(.in(Scopes.SINGLETON)),但该Singleton对象仅依赖于注入器,@Transactional是线程安全的。
- 在数据库存在被映射到一个注释FileContainer和被映射到对象MimeType的MIME类型表中的文件表。在应用程序中,当我们创建一个新文件时,我们首先检索MIMEType对象作为NamedQuery并保存它。
- 数据库是PostgreSQL 8.4,使用postgresql-8.4-702.jdbc3.jar。
- 该系统是适度的挑剔下,它失败的情况:我需要生成一个单独的线程,并从那里进行访问。
在第FileContainer对象mime类型字段的映射是:
@ManyToOne(fetch=FetchType.EAGER, cascade={})
@JoinColumn(name="mimetype_id", referencedColumnName="id", nullable=false, updatable=true)
将mimeType对象被注释如下:
@Entity
@Table(name="mimetypes")
@org.hibernate.annotations.Immutable
@Cacheable(true)
@NamedQuery(name="mt.ext", query="from MIMEType where extension = :ext",
hints= {@QueryHint(name="org.hibernate.fetchSize", value="1"),
@QueryHint(name="org.hibernate.readOnly", value="true")})
以上所有注释均为javax.persistence版本。
的addFile
方法注解为@com.google.inject.persist.Transactional
。将此更改为在类中使用注入的EntityManager似乎不会改变结果。
用于创建对象的方法是这样的:
- 抓住的EntityManager和从喷射器的FileDAO。这些都来自提供者。
- 抓住我们会从数据库中调用em.createNamedQuery使用的MIME类型对象(“mt.ext”,MIMEType.class).setParameter(“分机”,扩展)。getSingleResult();
- 创建
FileContainer
对象,并填充它,包括`setMimetype(MIME类型)的调用`与对象,我们只是取回 - 呼叫
dao.save(fileContainer)
,它设置在FileContainer
对象的基本字段,然后调用em.persist(Object)
。把它从DAO中拉出来,并使用之前注入的EntityManager
不会改变结果。
此时,只要发生EntityManager.flush()
(无论发生什么情况 - 在事务结束时或在它之前)INSERT发生并且代码发生死锁。
当我检查pg_stat_activity
并将其与pg_locks
进行比较时,我看到insert语句被一个“idle in transaction”连接阻塞,并且它处于等待状态。删除MIMEType的插入(并将列设置为允许空值)允许代码正常进行,并检查MIMEType的值表明它已正确检索。
任何想法或想法表示赞赏。
编辑:
这是层级,希望它澄清操作的顺序和正在发生的事情:
- 测试工具(初始化喷油器,并使用转轮把它注入到具体的测试班)
- 测试用例
- 开始线程
- 在线程内的单例对象(使用相同注入器初始化)上输入事务块,确认所有DAO对象中的对象都是相同的,并且发生错误的位置也是如此。
EntityManager
对象始终通过injector.getInstance(EntityManager.class)
调用或通过获取Provider
对象获得。- 通过上述过程,所有在同一个线程。
- 冻结
flush()
的代码没有出现有什么,应该是本地线程正在被线程和一切之间共享正在与喷油器,这是初始化是什么莫名其妙对我来说。
当然,让我们看看我能否澄清这种情况。 – 2011-03-26 03:06:31