Запуск собственного SELECT и UPDATE с JTA в одной транзакции - PullRequest
0 голосов
/ 17 января 2012

Я хотел бы знать, возможно ли выполнить оператор SELECT и UPDATE в Hibernate всего за одну транзакцию. Есть особая ситуация, которую я не могу изменить. Поэтому я должен вызвать функцию SQL, а затем ОБНОВИТЬ таблицу. Эта функция создает временные элементы, которые используются для обновления таблицы. Если он не вызывается в одной и той же транзакции, триггер вызывает сбой обновления.

Так что, пожалуйста, не говорите мне, что я должен изменить это: D я бы сделал, если бы мог. Но в любом случае ... вот мой код, который должен выполняться в одной транзакции, но который этого не делает:

 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
 public int nativeUpdateWithParams(String currentUser, boolean setCurrentUser, String nativeSql, Object...obj) {        
    try {
        Query query;
        if (nativeSql != null) {
            if (setCurrentUser) {
                String sql = "SELECT module.current_user(:param1)";
                query = em.createNativeQuery(sql);
                query.setParameter("param1", currentUser);
                query.getSingleResult();
            } 
            query = em.createNativeQuery(nativeSql);
            int i=0;
            for (Object param:obj) {
                i++;
                query.setParameter("param"+i, param);
            }
            int result = query.executeUpdate();
            return result;
        } else {
            return 0;
        }
    } catch (Exception ex) {                      
        ex.printStackTrace();
    } finally {            
        return 0;            
    }
}

Hibernate, кажется, создает по крайней мере две транзакции для выполнения SELECT и UPDATE. Если я изменю атрибут транзакции на:

@TransactionAttribute(TransactionAttributeType.MANDATORY)

создать транзакцию на клиенте (которую я всегда совершаю .. независимо от того, что происходит) и я пишу:

String test = "SELECT module.current_user('userXYZ')";
query = em.createNativeQuery(test + ";" + nativeSql);

я получаю исполнение, похожее на "update возвращает что-то ....", но оно работает. Было бы здорово, если бы кто-то помог мне решить эту проблему!

Спасибо

Edit: Исключение не поможет, потому что это результат триггера из таблицы «обновить».

Caused by: org.postgresql.util.PSQLException: FEHLER: You are not a real person.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1525)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1309)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:188)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:354)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:308)
at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:210)
... 72 more

Чтобы получить в деталях: если я делаю следующее на консоли / Postgres, он работает как шарм:

begin transaction;
SELECT module.current_user('userXYZ');
update public.carrier set carrier_comment='whatever' where carrier_id=57300;
commit;

я работаю!

если я сделаю это так:

SELECT module.current_user('userXYZ');
update public.carrier set carrier_comment='whatever' where carrier_id=57300;

я получаю ошибку, как описано выше: «Вы не настоящий человек»

Edit2: Если у кого-то есть такая же проблема, решение так же просто, как глупо :) Просто проверьте настройки Glassfish (JDBC - пулы соединений JDBC) и убедитесь, что вы не активировали:

Транзакция: нетранзакционные соединения: включено

Вот и все. После изменения этих настроек транзакция работает как положено. Так что это не было проблемой Hibernate ...

Привет!

1 Ответ

0 голосов
/ 17 января 2012

Конечно можно.Почему ты не мог?Как вы думаете, что делает Hibernate, когда вы говорите ему получить объект из БД, а затем обновить этот объект?Он выполняет запрос выбора SQL для получения объекта, а затем запрос обновления SQL для его обновления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...