简体   繁体   中英

SpringBoot + Hibernate JPA No EntityManager with actuall transaction in @Service Layer

I am configuring by myself Spring Boot application to run with two databases (two transactionManager same). MariaDB and MongoDB. And in @Repository where I have @Autowired with @PersistenceContext, the annotation @Transactional is working with properly TransactionManager. But for me the most useful is having @Transacional on the @Services layer. But when I have done this, I have a problem with

No EntityManager with actual transaction available for current thread

This is the configuration for @Repository and for JpaRepository (I will be coding on two way abstraction for extend my knowledge :) )

    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);
    }

}

And in the @Service I have a problem with "No EntityManager with actual transaction ..." I think I have to say SpringBoot about "Use this Transaction on the method" but my SpringBoot doesn't see TransactionManager in @Service layer yes? Because of in @Repository is everything ok when I add @Transactional.

How to configure that? Could you help me with that?

And simple @repository which is working well with @transactional, but I prefer @transactional in service layer (but now it doesn't work for me).

@Repository example:

@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);
    }
}

EDIT I tried @transactional for jpa and Spring context

    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);
        }
    }

Update the service layer to this :

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository){
        this.userRepository = userRepository;
    }

    @Transactional("MySQLTransactionManager")
    @PostConstruct
    public void createUser(){
        User newUser = new User("test");
        User usersaved = userRepository.addUserToDB(newUser);
    }
}

Ok. The problem is solved. What was wrong? If I removed @PostConstruct it is working now. But I can read on the documentation why @PostConstruct is not working with @Transactional ? Maybe is some of condition or configuration for that type? Because If I would like to have a transaction with database after Application was started? How is it possible? Only with @PostConstruct?

Thanks for afford your time for my problem :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM