powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Не работает @Transactional
7 сообщений из 7, страница 1 из 1
Не работает @Transactional
    #37898133
WGA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WGA
Гость
Привет всем!

Есть следующая проблема - похоже не работает аннотация @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
Не работает @Transactional
    #37898139
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Не работает @Transactional
    #37898216
WGA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WGA
Гость
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
Не работает @Transactional
    #37898231
WGA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WGA
Гость
Сорри, поторопился, не все варианты прокачал.
так не работает, транзакция не стартуется декларативно
Код: 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
Не работает @Transactional
    #37898270
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В spring есть TransactionTemplate, использовав который можно добиться нужного эффекта. ( мануал )
...
Рейтинг: 0 / 0
Не работает @Transactional
    #37898278
WGA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WGA
Гость
schwaВ spring есть TransactionTemplate, использовав который можно добиться нужного эффекта. ( мануал )Спасибо, буду изучать. Это все равно надо было штудировать, тем более что уже назрела проблема с коллекциями с lazy="extra" - hibernate не находит сессию. Так что надо еще браться и за управление сессиями хибернейта. Как принято на этом форуме: можно здесь продолжить или лучше новую тему?
...
Рейтинг: 0 / 0
Не работает @Transactional
    #37898296
WGA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WGA
Гость
Для полноты выкладываю вариант решения с 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
7 сообщений из 7, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Не работает @Transactional
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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