JPA更新查询 - 为什么我的交易不起作用?

时间:2011-11-05 18:53:29

标签: jpa eclipselink derby

我在编写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条记录的列表。这个调用集合需要超过500毫秒。如果Tally表是空的,那么该基准测试只有大约27ms,这大约是我希望看到的速度。当表填充到50,000行或更多行时,我看到500ms +数字。

如果有人对我发布我最终结果的结果感兴趣,请评论这样说。

P.S。这是在GlassFish下运行的JSF应用程序,而不是EJB。我不确定这与性能有关。

1 个答案:

答案 0 :(得分:5)

由于你有一个容器管理实体管理器,我猜你有把东西注入到EJB中。由于这种情况意味着事务由容器管理,即您不需要在代码中明确地启动它们。默认情况下,事务在EJB方法启动时启动,在该方法完成时结束。这适用于无状态EJB。对于有状态EJB,事务可以跨越多个方法调用,并在调用EJB“destroy”方法时结束。所以你应该决定:你要么使用一个容器管理的实体管理器(一个注入EJB,就像你在这里一样),你让容器管理trasactions(通过JTA),或者你做一个应用程序管理的实体管理器,你处理自己在代码中的交易。

关于性能,Apache的人说Derby在某些情况下对于生产,匹配甚至有时甚至超过MySQL和PostgreSQL都是非常好的,正如你在这个Apache文档中看到的那样:

http://home.online.no/~olmsan/publications/pres/apachecon05us/apachecon05.pdf

以一粒盐为例,德比因其表现而闻名世界。甚至这个文档也表明在某些情况下Derby比MySQL慢得多。此外,Derby上的CPU使用率更高。

我的建议:做一个概念验证,并在该数据库上进行基准测试。如果您将在生产中使用它,那么在不同的数据库上对您的应用进行性能调整没有多大意义。