Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Не работает @Transactional / 7 сообщений из 7, страница 1 из 1
30.07.2012, 17:50:38
    #37898133
WGA
WGA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
Привет всем!

Есть следующая проблема - похоже не работает аннотация @Transactional в связке Spring + Hibernate.
Бин для внесения в базу дефолтного админа
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
@Service
public class TestDataBuilder {

    public static final String DEFAULT_ADMIN_NAME = "admin";
    public static final String DEFAULT_ADMIN_PASSWORD = "admin";
    private UserService service;
    private RoleDao roleDao;

    @PostConstruct
    @Transactional
    public void postCostruct() {
        Role role = service.findRoleByName("SYSADMIN");
        if (role == null) {
            role = new Role();
            role.setRoleName("SYSADMIN");
            roleDao.save(role);
        }

        User user = service.findUserByName(DEFAULT_ADMIN_NAME);
        if (user == null) {
            user = new User();
            user.setUserName(DEFAULT_ADMIN_NAME);
            user.setFirstName("Admin");
            user.setLastName("Admin");
            user.getRoles().add(role);
            service.saveUser(user, DEFAULT_ADMIN_PASSWORD);
        }
    }

    @Autowired(required = true)
    public void setUserService(UserService userService) {
        this.service = userService;
    }

    @Autowired(required = true)
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }
}


Для получения хибернейтовской сессии во всех DAO использую SessionFactory#getCurrentSession(). Но если у метода UserService#findRoleByName заменить propagation на MANDATORY, то вызов метода падает с
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
.............. ну и стектрейс соответствующийЕсли правильно понимаю, это означает, что для метода postCostruct() аннотация не сработала. Что-то я не пойму в чем дело. Помогите, плз.
...
Рейтинг: 0 / 0
30.07.2012, 17:53:43
    #37898139
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
Transactional не работает в postConstruct, потому что postConstruct вызывается на бине, во время его создания. А Transactional работает через прокси, которые оборачивают бин.
/topic/951099
https://jira.springsource.org/browse/SPR-6002
http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct
...
Рейтинг: 0 / 0
30.07.2012, 18:59:28
    #37898216
WGA
WGA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
BlazkowiczTransactional не работает в postConstruct, потому что postConstruct вызывается на бине, во время его создания. А Transactional работает через прокси, которые оборачивают бин.
/topic/951099
https://jira.springsource.org/browse/SPR-6002
http://forum.springsource.org/showthread.php?58337-No-transaction-in-transactional-service-called-from-PostConstruct Спасибо за ссылки. Почитал, но все равно проблема пока не решена. Если я правильно понял, то выбор у меня такой:
1. Использовать AspectJ, т.е.
Код: plaintext
<tx:annotation-driven transaction-manager="txManager" mode="aspectj" />
2. Вызывать транзакционные метода после полной инициализации контекста по событию ApplicationListener<ContextRefreshedEvent>.

1. Первый рецепт я пока не хочу использовать.
2. Почему-то не работает. При собственной реализации листенера та же самая ошибка, что транзанкция не запущена, а при использовании аннотации @PostInitialize метод createDefaultAdmin() вообще не находится.
переработанный TestDataBuilder
Код: java
\r\npublic class TestDataBuilderImpl implements TestDataBuilder {\r\n\r\n    public static final String DEFAULT_ADMIN_NAME = "admin";\r\n    public static final String DEFAULT_ADMIN_PASSWORD = "admin";\r\n    private UserService service;\r\n    private RoleDao roleDao;\r\n\r\n    @Transactional(propagation = Propagation.REQUIRED)\r\n    @PostInitialize\r\n    public void createDefaultAdmin() {\r\n        User user = service.findUserByName(DEFAULT_ADMIN_NAME);\r\n        if (user == null) {\r\n            Role role = service.findRoleByName("SYSADMIN");\r\n            if (role == null) {\r\n                role = new Role();\r\n                role.setRoleName("SYSADMIN");\r\n                roleDao.save(role);\r\n            }\r\n            user = new User();\r\n            user.setUserName(DEFAULT_ADMIN_NAME);\r\n            user.setFirstName("Admin");\r\n            user.setLastName("Admin");\r\n            user.getRoles().add(role);\r\n            service.saveUser(user, DEFAULT_ADMIN_PASSWORD);\r\n        }\r\n    }\r\n\r\n    @Autowired(required = true)\r\n    public void setUserService(UserService userService) {\r\n        this.service = userService;\r\n    }\r\n\r\n    @Autowired(required = true)\r\n    public void setRoleDao(RoleDao roleDao) {\r\n        this.roleDao = roleDao;\r\n    }\r\n}\r\n
\r\n
...
Рейтинг: 0 / 0
30.07.2012, 19:17:11
    #37898231
WGA
WGA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
Сорри, поторопился, не все варианты прокачал.
так не работает, транзакция не стартуется декларативно
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
public class TestDataBuilderImpl implements TestDataBuilder, ApplicationListener<ContextRefreshedEvent> {

    public static final String DEFAULT_ADMIN_NAME = "admin";
    public static final String DEFAULT_ADMIN_PASSWORD = "admin";
    private UserService service;
    private RoleDao roleDao;

    @Transactional
    @PostInitialize
    public void createDefaultAdmin() {
        User user = service.findUserByName(DEFAULT_ADMIN_NAME);
        if (user == null) {
            Role role = service.findRoleByName("SYSADMIN");
            if (role == null) {
                role = new Role();
                role.setRoleName("SYSADMIN");
                roleDao.save(role);
            }
            user = new User();
            user.setUserName(DEFAULT_ADMIN_NAME);
            user.setFirstName("Admin");
            user.setLastName("Admin");
            user.getRoles().add(role);
            service.saveUser(user, DEFAULT_ADMIN_PASSWORD);
        }
    }

    @Autowired(required = true)
    public void setUserService(UserService userService) {
        this.service = userService;
    }

    @Autowired(required = true)
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        createDefaultAdmin();
    }
}

а вот так заработало
рабочий код
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
public class TestDataBuilderImpl implements TestDataBuilder, ApplicationListener<ContextRefreshedEvent> {

    public static final String DEFAULT_ADMIN_NAME = "admin";
    public static final String DEFAULT_ADMIN_PASSWORD = "admin";
    private UserService service;
    private RoleDao roleDao;

    @PostInitialize
    public void createDefaultAdmin() {
        User user = service.findUserByName(DEFAULT_ADMIN_NAME);
        if (user == null) {
            Role role = service.findRoleByName("SYSADMIN");
            if (role == null) {
                role = new Role();
                role.setRoleName("SYSADMIN");
                roleDao.save(role);
            }
            user = new User();
            user.setUserName(DEFAULT_ADMIN_NAME);
            user.setFirstName("Admin");
            user.setLastName("Admin");
            user.getRoles().add(role);
            service.saveUser(user, DEFAULT_ADMIN_PASSWORD);
        }
    }

    @Autowired(required = true)
    public void setUserService(UserService userService) {
        this.service = userService;
    }

    @Autowired(required = true)
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }

    @Transactional // необходимо накладывать на обработчик, поскольку иначе createDefaultAdmin вызывается без прокси, а напрямую
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        createDefaultAdmin();
    }
}

Понимаю, что это метод полунаучного тыка, но я не настолько понимаю внутренню логику работы Spring, чтобы действовать осмысленно. Собственно, я и с Java-то работаю не так давно.

PS В прошлом сообщении забыл указать ссылку откуда взял @PostInitialize - отсюда . Но у меня эта штука не работает вообще, не находит нужную аннотацию на методе судя по отладке.
...
Рейтинг: 0 / 0
30.07.2012, 20:07:47
    #37898270
schwa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
В spring есть TransactionTemplate, использовав который можно добиться нужного эффекта. ( мануал )
...
Рейтинг: 0 / 0
30.07.2012, 20:17:44
    #37898278
WGA
WGA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
schwaВ spring есть TransactionTemplate, использовав который можно добиться нужного эффекта. ( мануал )Спасибо, буду изучать. Это все равно надо было штудировать, тем более что уже назрела проблема с коллекциями с lazy="extra" - hibernate не находит сессию. Так что надо еще браться и за управление сессиями хибернейта. Как принято на этом форуме: можно здесь продолжить или лучше новую тему?
...
Рейтинг: 0 / 0
30.07.2012, 20:31:03
    #37898296
WGA
WGA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает @Transactional
Для полноты выкладываю вариант решения с TransactionTemplate:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
public class TestDataBuilderImpl {

    public static final String DEFAULT_ADMIN_NAME = "admin";
    public static final String DEFAULT_ADMIN_PASSWORD = "admin";
    private UserService service;
    private RoleDao roleDao;
    @Autowired
    private PlatformTransactionManager transactionManager;

    @PostConstruct
    public void createDefaultAdmin() {
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                User user = service.findUserByName(DEFAULT_ADMIN_NAME);
                if (user == null) {
                    Role role = service.findRoleByName("SYSADMIN");
                    if (role == null) {
                        role = new Role();
                        role.setRoleName("SYSADMIN");
                        roleDao.save(role);
                    }
                    user = new User();
                    user.setUserName(DEFAULT_ADMIN_NAME);
                    user.setFirstName("Admin");
                    user.setLastName("Admin");
                    user.getRoles().add(role);
                    service.saveUser(user, DEFAULT_ADMIN_PASSWORD);
                }

            }
        });
    }

    @Autowired(required = true)
    public void setUserService(UserService userService) {
        this.service = userService;
    }

    @Autowired(required = true)
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }
}

...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Не работает @Transactional / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]