Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / EclipseLink + Spring @Transactional / 5 сообщений из 5, страница 1 из 1
09.06.2016, 13:05
    #39253540
SergWF
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
EclipseLink + Spring @Transactional
Всем доброго дня.

Возникла нужда в имеющемся Spring-boot приложении мигировать от Hibernate на EclipseLink.
В процессе миграции обнаружилась странная особенность. Если метод помечен как @org.springframework.transaction.annotation.Transactional, то ВНУТРИ МЕТОДА при сохранении нового entity репозиторий возвращает неизмененный объект (entity.id == null).
Если на методе нет аннотации @Transactional и/или транзакция стартует "мануально", то все ок, entity.id содержит значение первичного ключа.
Такое поведение началось только после миграции на EclipseLink.

Тут ошибка:
Код: java
1.
2.
3.
4.
5.
6.
    
    @Transactional
    public Employee createEmployee(){
        Employee employee = employeeRepository.save(new Employee("vasya", "pupkin"));
        processEmployee(employee); //employee.id == null
    }


транзакция запускается явно, все Ок:
Код: java
1.
2.
3.
4.
5.
6.
    public Employee createEmployee(){
       TransactionStatus status = transactionManager.getTransaction(createDefinition("trCreateEmployee"));
            Employee employee = employeeRepository.save(new Employee("vasya", "pupkin"));
            processEmployee(employee); //employee.id==1234
      transactionManager.commit(transaction);
    }



Нет @Transactional, тоже все Ок:
Код: java
1.
2.
3.
4.
    public Employee createEmployee(){
            Employee employee = employeeRepository.save(new Employee("vasya", "pupkin"));
            processEmployee(employee); //employee.id==1234
    }




Конфигурация:
Код: 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.
46.
47.
48.
49.
50.
@Configuration
@EnableJpaRepositories
@EnableJpaAuditing
@EntityScan
@PropertySource("classpath:storage.properties")
@ComponentScan
@EnableAutoConfiguration
public class StorageConfig extends JpaBaseConfiguration {
    private static Logger logger = LoggerFactory.getLogger(StorageConfig.class);

    @Autowired
    private JpaProperties jpaProperties;

    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
        final EclipseLinkJpaDialect customDialect = new EclipseLinkJpaDialect() {
            @Override
            public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) throws
                    PersistenceException, SQLException {
                // Hides: return super.getJdbcConnection(entityManager, readOnly);
                return null;
            }
        };

        customDialect.setLazyDatabaseTransaction(false);

        return new EclipseLinkJpaVendorAdapter(){
            @Override
            public EclipseLinkJpaDialect getJpaDialect() {
                return customDialect;
            }
        };
    }

    @Override
    protected Map<String, Object> getVendorProperties() {
        Map<String, Object> vendorProperties = new LinkedHashMap<>();
        vendorProperties.putAll(this.jpaProperties.getProperties());
        vendorProperties.put(PersistenceUnitProperties.BATCH_WRITING, BatchWriting.JDBC);
        vendorProperties.put(PersistenceUnitProperties.WEAVING, "static");
        vendorProperties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "auto");
        vendorProperties.put(PersistenceUnitProperties.TARGET_DATABASE, TargetDatabase.PostgreSQL);
        return vendorProperties;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}



Репозиторий:
Код: java
1.
2.
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}


Как можно исправить поведение @Transactional?
...
Рейтинг: 0 / 0
09.06.2016, 13:22
    #39253568
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
EclipseLink + Spring @Transactional
В принципе, поведение объяснимое. Интересно было бы разобраться почему в Hibernate работало.
В ручном управлении транзакцией есть подозрение, что эта транзакция просто не распространяется на репозиторий, и получается то же самое что и при отсутствии @Transactional. То есть в этих двух случаях репозиторий делает коммит.

В случае же с открытой транзакцией ни flush ни коммит не происходит. Возможно, в Hibernate на этот случай есть костыль, чтобы гарантировать наличие id, он такие делает flush.
...
Рейтинг: 0 / 0
09.06.2016, 13:23
    #39253571
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
EclipseLink + Spring @Transactional
SergWF,

Вот тут ещё приведены настройки EclipseLink по делу
http://stackoverflow.com/a/19846340
Есть смысл попробовать.
...
Рейтинг: 0 / 0
09.06.2016, 13:30
    #39253590
SergWF
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
EclipseLink + Spring @Transactional
Для получения Id нет необходимости коммитить данные. Но записать данные в БД JPA вполне может. Что Hibernate и делает. Похоже EclipseLink персистит объекты как-то иначе. Надеюсь, что существует возможность изменить это поведение конфигурацией.
...
Рейтинг: 0 / 0
09.06.2016, 14:10
    #39253643
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
EclipseLink + Spring @Transactional
SergWFДля получения Id нет необходимости коммитить данные.
Речь не о коммите. Для коммита требуется flush. И для генерации Id требуется flush. Поэтому там где был коммит, на уровне репозитория, там был и flush. А там где не было коммита, не было и flush и id null-овый.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / EclipseLink + Spring @Transactional / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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