【发布时间】:2011-12-22 18:35:18
【问题描述】:
我在编写事务时遇到了 JavaDB (Derby) 性能问题。每笔交易需要 500 多毫秒,我一天可能有几十万。我期待部署在 MySql 上,我不知道我是否会在那里遇到同样的问题,但我在尝试之前尝试提高 Derby 的性能。
一个事务涉及更新一串记录 - 多达 6 个,如下所示:
public void update(List<Tally> list) {
try {
utx.begin();
for (Tally tally : list) em.merge(tally);
utx.commit();
// etc
我想看看 UPDATE 查询是否会更好,因为 JPA 不必跟踪更新的列并组成 SQL 查询(附带问题:这是一个好的理论吗?)
所以我编写了一个如下所示的命名查询:
@NamedQuery(name="TallyUpdate",
query="UPDATE Tally t SET t.vote = t.vote + 1 WHERE t.id IN :idSet"
就是这样操作的:
@PersistenceContext protected EntityManager em;
@Resource protected UserTransaction utx;
public void incrementVote(List<Long> idList) {
Query q = em.createNamedQuery("TallyUpdate");
q.setParameter("idSet", idList);
try {
utx.begin();
q.executeUpdate();
utx.commit();
//etc
executeUpdate() 调用总是抛出异常:
SEVERE: javax.persistence.TransactionRequiredException: executeUpdate is not supported for a Query object obtained through non-transactional access of a container-managed transactional EntityManager
at com.sun.enterprise.container.common.impl.QueryWrapper.executeUpdate(QueryWrapper.java:225)
JPA 实现是 EclipseLink 2.3.0
这个词沙拉异常是什么意思,我应该如何运行更新?
结果发布:
我确实将 createnamedQuery() 调用移到了 utx.begin() 调用之后,并且更新开始工作。我不知道为什么,但我现在要使用它。目前还没有关于相对表现的结果,但我在上面的帖子具有误导性。当计票时,计票方式大约是 24-36 种,而不是 6 种。所以对原始的 update() 方法(使用 merge())有 6 次调用) 每个都有大约 6 条记录的列表。正是这个调用集合需要超过 500 毫秒。如果 Tally 表是空的,那么该基准只有大约 27 毫秒,这大约是我希望看到的速度。当表格填充到 50,000 行或更多行时,我会看到 500 毫秒以上的数字。
如果有人对我发布最终结果的结果感兴趣,请发表评论。
附:这是在 GlassFish 而非 EJB 下运行的 JSF 应用程序。我不确定这是否与性能有关。
【问题讨论】:
标签: jpa eclipselink derby