2015-08-04 3 views
0

Я использую grails 1.3.7 вместе с Oracle 11g и пытаюсь управлять внутренними транзакциями. У меня есть bean-компонент, который передается транзакционному (Propagation.REQUIRED) метод обслуживания, который делает некоторые изменения. Затем он передается другому транзакционному методу (propation = Propagation.REQUIRES_NEW), который выполняет некоторые другие модификации и затем выдает исключение. То, что я ожидал увидеть, - это откат всех модификаций второй службы, но все еще действительный для первого. В этой ситуации:grails Вложенная транзакция bean reset

//outer transaction 
class MyService { 

    def nestedService 

    @Transactional(propagation = Propagation.REQUIRED) 
    public void testRequiredWithError(Person person) { 
     person.name = 'Mark' 
     try { 
      nestedService.testRequiresNewWithError(person) 
     } catch (RuntimeException e) { 
      println person.age //this prints 15 
      println e 
     } 
    } 
}//end MyService 

//inner transaction 
class NestedService{ 

    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    public void testRequiresNewWithError(Person person) { 
     person.age = 15 //expected after Exception will be discarded 
     throw new RuntimeException("Rollback this transaction!") 
    } 
} 

Затем я запускаю консоль Грайля и проверяю БД после его завершения. ...

def p = Person.get(671) 
    def myService = ctx.myService 

    println p.name //'John'...from DB 
    println p.age //25...from DB 

    myService .testRequiredWithError(p) 

    println p.name // 'Mark'....correct 
    println p.age // 15....UNEXPECTED.. 
    //same result checking on the DB after console ends and transaction flushes 

Я пытался использовать Propagation.NESTED после его активации в начальной загрузки по transactionManager.setNestedTransactionAllowed(true) и использовать как точки сохранения на этом посту grails transaction set savepoint , но все-таки получил тот же результат.

Что мне не хватает ????

Заранее спасибо.

+0

для вашего теста, попробуйте очистить сеанс, а затем повторите попытку. grailsApplication.getCurrentSession(). clear() – juandiegoh

+0

Откат на уровне базы данных не на уровне объекта. Но я не уверен, что если ваш откат REQUIRES_NEW устанавливает ваш возраст как грязный или нет. Если это не так, то при повторном поиске в базе данных (после очистки сеанса) возраст будет равен 25. – juandiegoh

+0

Благодарим вас за советы. Я уже пытался очистить сеанс, но все тот же. Я почти уверен, что вы правы, что возраст не установлен как грязный beacause, я вижу, что он сохранялся в БД. Еще раз спасибо за ответ. – albe

ответ

0

Я проверил для p.isAttached(), так как откат транзакции отделяет объект домена от сеанса Hibernate. Также в тесте я перезагрузил объект домена из базы данных - снова p = Person.get(671) снова, чтобы перезагрузить данные из базы данных.

Я думаю, что по умолчанию свойство age установлено после 15-го теста, после чего объект домена и база данных не синхронизированы (и объект домена отсоединен).

подробнее см: https://weblogs.java.net/blog/blog/davidvc/archive2007/04/jpa_and_rollbac.html

+0

Благодарим вас за ответ. Я попытался проверить isAttached(), но он возвращает true. Я также попытался перезагрузить, используя get (..), но получаю тот же результат. – albe

1

Я немного опоздал на вечеринку, но в случае, если вы не нашли ответ на свой вопрос, я думаю, я знаю, почему у вас возникли проблемы с операциями.

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

http://www.tutorialspoint.com/mysql/mysql-transactions.htm

EDIT: Эта статья предлагает установку типа Вашей таблицы в InnoDB в целях поддержки операций , Вот пример того, как это выглядит:

mysql> create table tcount_tbl 
    -> (
    -> tutorial_author varchar(40) NOT NULL, 
    -> tutorial_count INT 
    ->) TYPE=InnoDB; 

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

Надеюсь, это поможет!

+0

Пожалуйста, включите соответствующие данные в свой ответ, поскольку ссылки могут со временем сломаться. – tsnorri

+1

Хорошо, я отредактировал свой ответ, чтобы он больше не полагался на ссылку. Еще немного нового в этом LOL. –

Смежные вопросы