#java #hibernate #spring-mvc #jpa #spring-data-jpa
#Ява #зимовать #весна-mvc #jpa #весна-данные-jpa
Вопрос:
Я переношу приложение из простого режима гибернации в JPA, поэтому мне нужно, чтобы многие DAO, которые у нас есть, работали, но также имели репозитории JPA для обработки некоторых таблиц в некоторых случаях использования.
У меня возникли проблемы с транзакциями. Я вызываю метод службы, который является @Транзакционным, с простого контроллера, но я получаю эту трассировку стека :
javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:431) ~[hibernate-core-5.6.1.Final.jar:5.6.1.Final] at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3492) ~[hibernate-core-5.6.1.Final.jar:5.6.1.Final] at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1408) ~[hibernate-core-5.6.1.Final.jar:5.6.1.Final] at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1403) ~[hibernate-core-5.6.1.Final.jar:5.6.1.Final] at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:113) ~[spring-orm-5.3.13.jar:5.3.13] at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95) ~[spring-orm-5.3.13.jar:5.3.13] at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:97) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:916) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:727) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.13.jar:5.3.13] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.13.jar:5.3.13] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.13.jar:5.3.13] at com.sun.proxy.$Proxy144.myActualServiceMethod(Unknown Source) ~[?:?]
Вот моя конфигурация JpaConfiguration :
@Configuration @EnableJpaRepositories( basePackages = { "com.myapp.project.metier.domain.dao.repos" } ) @EnableTransactionManagement @EnableJpaAuditing(auditorAwareRef = "jpaAuditorProvider") public class JpaConfig { @Bean public AuditorAwarelt;Stringgt; jpaAuditorProvider() { return new UsernameAuditorAware(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPackagesToScan("com.myapp.project.metier.domain.entities"); em.setPersistenceUnitName("MyPersistenceUnit"); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(additionalProperties()); return em; } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3307/my_database"); dataSource.setUsername("root"); dataSource.setPassword("rootmdp"); return dataSource; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); jpaTransactionManager.setEntityManagerFactory(entityManagerFactory); return jpaTransactionManager; } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { return new PersistenceExceptionTranslationPostProcessor(); } final Properties additionalProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.show_sql", "false"); hibernateProperties.setProperty("hibernate.format_sql", "false"); hibernateProperties.setProperty("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext"); // hibernateProperties.setProperty("hibernate.current_session_context_class", "thread"); // hibernateProperties.setProperty("hibernate.current_session_context_class", // "jta"); // "org.springframework.orm.hibernate5.SpringSessionContext"); // hibernateProperties.setProperty("hibernate.transaction.jta.platform", // "org.jadira.usertype.spi.jta.LocalTransactionManagerPlatform"); return hibernateProperties; } // needed by the old DAOs that are not JPA repositories @Bean public SessionFactory sessionFactory(EntityManagerFactory entityManagerFactory) { HibernateJpaSessionFactoryBean hibernateJpaSessionFactoryBean = new HibernateJpaSessionFactoryBean(); hibernateJpaSessionFactoryBean.setEntityManagerFactory(entityManagerFactory); return hibernateJpaSessionFactoryBean.getObject(); // this causes an exception even though the documentation says it should be used // org.springframework.orm.jpa.JpaSystemException: Could not obtain transaction-synchronized Session for current thread; nested exception is org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread /*return entityManagerFactory.unwrap(SessionFactory.class);*/ }
}
Остальная часть моей конфигурации-это XML-файлы (это старое приложение Spring MVC).
Спасибо вам за вашу помощь
Комментарии:
1. Удалите
LocalEntityManagerFactory
и настройтеLocalSessionFactory
вместо этого. Начиная с hibernate 5.3SessionFactory
, он также являетсяEntityManagerFactory
. Так что вам нужен только один.2. Я удалил
LocalContainerEntityManagerFactoryBean
компонент и добавил@Bean public LocalSessionFactoryBean sessionFactory(DataSource dataSource) { }
, что теперь я получаюNoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
ошибку, когда репозитории JPA пытаются создать экземпляр. Хотя в документацииLocalSessionFactory
говорится об очень интересных вещах, неясно, как это реализовать, я буду копать.3. Переименуйте метод в
entityManagerFactory
или поместите оба имени компонента в@Bean
аннотацию. Также убедитесь, что вы подключаете это кJpaTransactionManager
(theSessionFactory
).4. Я сделал это
@Bean(name = {"entityManagerFactory", "sessionFactory"}) public LocalSessionFactoryBean sessionFactory(DataSource dataSource)
, и это сработало ! Но сJpaTransactionManager
помощью (того же, что и в исходном сообщении) код был запущен, но в БД ничего не было записано. поэтому я переключился наHibernateTransactionManager
, и теперь он хорошо работает с транзакциями ! Спасибо вам 🙂 Не знаю, хорошо ли это» не использоватьJpaTransactionManager
«, хотя