Я сам настраиваю приложение Spring Boot для работы с двумя базами данных (две транзакции одинаковые). MariaDB и MongoDB. А в @Repository, где у меня @Autowired с @PersistenceContext, аннотация @Transactional работает с должным образом TransactionManager. Но для меня самым полезным является наличие @Transacional на слое @Services. Но когда я это сделал, у меня возникла проблема с
No EntityManager with actual transaction available for current thread
Это конфигурация для @Repository и для JpaRepository (я буду писать двухстороннюю абстракцию для расширения моих знаний :))
package com.kamil.serwis.config;
@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryMySQL",
basePackages = "com.kamil.serwis.repository",
transactionManagerRef = "MySQLTransactionManager")
@EnableTransactionManagement
@ComponentScan(basePackages = {"com.kamil.serwis.repository.dao.SQL"})
public class HibernateConfiguration {
private final String URLDatabase = "jdbc:mariadb://localhost:3306/SerwisDB";
private final String User = "test";
private final String Password = "password";
private final String SQLDatabase = "org.mariadb.jdbc.Driver";
@Bean(name ="entityManagerFactoryMySQL")
@Primary
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean emf =
new LocalContainerEntityManagerFactoryBean();
emf.setPackagesToScan("com.kamil.serwis.model.SQL");
emf.setDataSource(createDataSource());
emf.setJpaVendorAdapter(createJpaVendorAdapter());
emf.setJpaProperties(createHibernateProperties());
emf.setPersistenceUnitName("MySQLPersistence");
// emf.afterPropertiesSet();
System.out.println("Data source do bazy" + emf.getDataSource().toString() + " " +emf.getPersistenceUnitName());
return emf;
}
@Primary
private DataSource createDataSource() {
DataSource dataSource= DataSourceBuilder.create()
.url(this.URLDatabase)
.username(User)
.password(Password)
.driverClassName(SQLDatabase)
.build();
return dataSource;
}
@Primary
private JpaVendorAdapter createJpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Primary
private Properties createHibernateProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create");
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL55Dialect");
properties.setProperty("hibernate.show_sql","true");
/*properties.setProperty("com.mysql.cj.jdbc.Driver","");*/
return properties;
}
@Bean(name = "MySQLTransactionManager")
@Primary
PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactoryMySQL") EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
И в @Service у меня проблема с «Нет EntityManager с реальной транзакцией ...» Я думаю, что должен сказать SpringBoot о «Использовать эту транзакцию в методе», но мой SpringBoot не видит TransactionManager в слое @Service да? Потому что в @Repository все нормально, когда я добавляю @ Transactional.
Как это настроить? Не могли бы вы помочь мне с этим?
И простой @repository, который хорошо работает с @transactional, но я предпочитаю @transactional на уровне сервиса (но теперь он не работает для меня).
@ Пример репозитория:
@Repository
public class UserRepository {
@PersistenceContext(name = "MySQLPersistence")
@Autowired
private EntityManager entityManager;
public User addUserToDB(User newUser){
entityManager.persist(newUser);
return newUser;
}
public User findUserByName(String userName){
User user = (User)entityManager.createQuery( "select u from User u").getResultStream().findFirst().get();
return user;
}
public boolean deleteUser(User userToDelete){
entityManager.remove(userToDelete);
return entityManager.find(User.class,userToDelete.getId()).equals(userToDelete);
}
}
РЕДАКТИРОВАТЬ Я пытался @transactional для контекста jpa и Spring
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.transaction.TransactionManager;
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository){
this.userRepository = userRepository;
}
@Transactional(transactionManager = "entityManagerFactoryMySQL")
//@javax.transaction.Transactional
@PostConstruct
public void createUser(){
User newUser = new User("test");
User usersaved = userRepository.addUserToDB(newUser);
}
}