简体   繁体   中英

Why didn't @Transactional work with @Autowired EntityManagerFactory?

I had a problem with persisting objects to the database using Spring 4.3, JPA 2.1 and Hibernate 5. Figured out something was wrong with transactions. Here is my configuration:

@Configuration
@EnableTransactionManagement
public class PersistenceConfig {

   /**
     * most bean methods skipped, left only the relevant ones
    **/


    @Bean
    @Autowired
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        entityManagerFactoryBean.setPackagesToScan("com.company");
        entityManagerFactoryBean.setJpaProperties(jpaProperties());
        return entityManagerFactoryBean;
    }

    @Bean
    @Autowired
    JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }

Here is my service. The code has run, no exceptions were thrown. But the object was not persisted to the database. I have intuitively understood that either something was wrong with a transaction creation (as the logger didn't show any transactions) or data was not committed to the database. EntityManagerFactory was not null .

@Service
public class Manager {

@Autowired
private EntityManagerFactory entityManagerFactory;

@Transactional
public void persist(Entity entity){
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.persist(entity);
}

}

After I replaced @Autowired EntityManagerFactory with @javax.persistence.PersistenceContext EntityManager , everything worked fine.

@Service
public class Manager {

@javax.persistence.PersistenceContext
private EntityManager entityManager;


@Transactional
public void persist(Entity entity){
    entityManager.persist(entity);
}

}

Why doesn't it work with @Autowired EntityManagerFactory ?

You are using Spring for transaction management and as such you want to get the current transactional EntityManager . If you are injecting the EntityManagerFactory and use it to get an EntityManager you have a good change you end up with a new one, this new one isn't bound to the started transaction.

Instead inject the EntityManager using @PersistenceContext

@PersistenceContext
private EntityManager em.

If you really want to inject the EntityMangerFactory you have to use @PersistenceUnit instead of @Autowired . The @PersistenceUnit is handled different then a plain @Autowired .

@PersistenceUnit
private EntityManagerFactory emf;

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