JPA Update Query - Почему моя транзакция не работает? - PullRequest
2 голосов
/ 05 ноября 2011

У меня проблема с производительностью транзакций записи 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

THE 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 пуста, то этот тест составляет всего около 27 мс, что соответствует скорости, которую я хотел бы видеть.Число 500 мс + - это то, что я вижу, когда таблица заполняется до 50 000 или более строк.

Если кто-то заинтересован в том, чтобы я опубликовал результаты, в которых я остановился на этом, пожалуйста, прокомментируйте так.

PS Это приложение JSF, работающее под GlassFish, а не EJB.Я не уверен, есть ли какие-либо последствия, связанные с производительностью.

1 Ответ

5 голосов
/ 05 ноября 2011

Поскольку у вас есть диспетчер управляемых сущностей контейнеров, я предполагаю, что вы внедрили эту вещь в EJB.Поскольку это так, это означает, что транзакции управляются контейнером, т.е. вам не нужно явно запускать их в своем коде.По умолчанию транзакция начинается, когда метод EJB запускается, и заканчивается, когда этот метод заканчивается.Это для EJB без гражданства.Для полнофункциональных EJB-транзакций транзакция может охватывать несколько вызовов методов и завершаться при вызове EJB-методов "destroy".Поэтому вы должны решить: либо вы используете диспетчер сущностей, управляемый контейнером (один из которых внедрен в EJB, как у вас здесь), и вы позволяете контейнеру управлять транзакциями (через JTA), либо вы создаете менеджер сущностей, управляемый приложением, и вы обрабатываетесами транзакции в коде.

Что касается производительности, ребята из Apache говорят, что Derby идеально подходит для производства, сопоставления и иногда даже превосходства MySQL и PostgreSQL в определенных сценариях, как вы можете видеть в этом документе Apache:

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

Примите во внимание, что с долей соли Дерби не всемирно известен своей производительностью.И даже этот документ показывает, что в определенных ситуациях Derby намного медленнее, чем MySQL.Также загрузка ЦП на Derby выше.

Мой совет: сделайте проверку концепции MySQL и сделайте свои тесты на этой базе данных.Если это то, что вы собираетесь использовать в производственной среде, не имеет смысла производить настройку производительности вашего приложения в другой базе данных.

...