2015-11-25 2 views
1

У меня возникла проблема с сохраняющимися объектами в базе данных с использованием Spring 4.3, JPA 2.1 и Hibernate 5. Выяснилось, что с транзакциями было что-то не так. Вот моя конфигурация:Почему @Transactional не работал с @Autowired EntityManagerFactory?

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

Вот моя служба. Код запущен, никаких исключений не было. Но объект не сохранялся в базе данных. Я интуитивно понял, что что-то не так с созданием транзакции (поскольку регистратор не показывал никаких транзакций), или данные не были переданы в базу данных. EntityManagerFactoryне было null.

@Service 
public class Manager { 

@Autowired 
private EntityManagerFactory entityManagerFactory; 

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

} 

После того как я заменил @Autowired EntityManagerFactory с @javax.persistence.PersistenceContext EntityManager, все работало отлично.

@Service 
public class Manager { 

@javax.persistence.PersistenceContext 
private EntityManager entityManager; 


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

} 

Почему это не работает с @Autowired EntityManagerFactory?

+2

Поскольку вы создаете новый 'EntityManager' с тем, что не является транзакционным диспетчером объектов, следовательно, не совершать на' EntityManager' используется для вызова 'persist' на. При автоматической проводке 'EntityManager' вы получите транзакционный' EntityManager'. –

+0

@ M.Deinum: не могли бы вы добавить свой комментарий в качестве ответа, так что я смогу принять его? – nmeln

ответ

1

Вы используете Spring для управления транзакциями и как таковой вы хотите получить текущую транзакцию EntityManager. Если вы вводите EntityManagerFactory и используете его для получения EntityManager, у вас есть хорошие изменения, вы получите новый, новый не связан с начатой ​​транзакцией.

Вместо впрыскивать EntityManager с помощью @PersistenceContext

@PersistenceContext 
private EntityManager em. 

Если вы действительно хотите, чтобы впрыснуть EntityMangerFactory вы должны использовать @PersistenceUnit вместо @Autowired. @PersistenceUnit обрабатывается другой, а затем простой @Autowired.

@PersistenceUnit 
private EntityManagerFactory emf;