【问题标题】:JPA Update Query -- Why won't my transaction work?JPA 更新查询——为什么我的事务不能工作?
【发布时间】: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


    【解决方案1】:

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

    关于性能,Apache 人员说 Derby 非常适合生产,在某些情况下可以匹配甚至有时甚至超过 MySQL 和 PostgreSQL,正如您在此 Apache 文档中看到的那样:

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

    尽管如此,德比并没有因其表现而闻名于世。甚至这份文档也表明,在某些情况下,Derby 比 MySQL 慢很多。此外,Derby 的 CPU 使用率也更高。

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

    【讨论】:

      猜你喜欢
      • 2015-08-26
      • 1970-01-01
      • 2012-04-15
      • 1970-01-01
      • 2021-11-28
      • 2014-08-07
      • 2017-01-25
      • 2012-08-15
      • 1970-01-01
      相关资源
      最近更新 更多