nmeln
nmeln

Reputation: 495

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?

Upvotes: 3

Views: 1707

Answers (1)

M. Deinum
M. Deinum

Reputation: 124998

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;

Upvotes: 3

Related Questions