2015-09-14 2 views
11

Я использую JPA в своем приложении, и он работает, как только я запрашиваю объекты, однако он бросает ошибку javax.persistence.TransactionRequiredException: No transactional EntityManager available после того, как попытался сохранить или обновить объект.Невозможно сохранить/обновить объект с помощью JPA весной

Это конфигурация Java:

@Configuration 
@EnableTransactionManagement(proxyTargetClass = true) 
@PropertySource("classpath:dao.properties") 
public class JpaConfig { 
    @Autowired 
    private Environment env; 
    @Bean 
    public DataSource dataSource() { 
     BasicDataSource dataSource = new BasicDataSource(); 
     ..................... 
     return dataSource; 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     Properties jpaProperties = new Properties(); 
     jpaProperties.put("hibernate.dialect", ...........) 

     LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
     entityManagerFactoryBean.setDataSource(dataSource()); 
     entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
     entityManagerFactoryBean.setJpaProperties(jpaProperties); 
     entityManagerFactoryBean.setPackagesToScan("com...."); 
     return entityManagerFactoryBean; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); 
     return transactionManager; 
    } 
} 

Примечание Я использую proxyTargetClass = true в @EnableTransactionManagement, так как я не хочу создавать бесполезные интерфейсы в моем приложении.

И это бетон РЕАЛИЗАЦИЯ из дао:

@Transactional 
@Repository 
public abstract class AbstractJPADao<I, E> { 
    @Autowired 
    @PersistenceContext 
    protected EntityManager entityManager; 

    private Class<E> type; 
    public AbstractJPADao() { 
     type=.... 
    } 

    @Override 
    public Result<E> find(I id) { 
     E e = entityManager.find(type, id); 
     return Result.newInstance().setContent(e); 
    } 

    @Override 
    public Result<E> find(Map<String, Object> condition) { 
     Query q = entityManager.createQuery(".......)); 
     return Result.newInstance().setContent(q.getResultList()); 
    } 

    @Override 
    public E save(E element) { 
     entityManager.persist(element); 
     return element; 
    } 
    @Override 
    public E update(E element) { 
     entityManager.merge(element); 
     return element; 
    } 

    @Override 
    public void delete(E element) { 
     entityManager.remove(element); 
    } 
} 

@Repository 
@Transactional 
public class DepartmentDao extends AbstractJPADao<String, Department> { 
    @Override 
    protected String selectCause(Map<String, Object> condition) { 
     return ""; 
    } 
} 

И контроллер в качестве клиента дао:

@Controller 
@RequestMapping("/api/deps") 
public class DepartmentCtrl { 
    @Autowired 
    private DepartmentDao departmentDao; 
    @RequestMapping(value = "", method = RequestMethod.POST) 
    public Result create(@Valid Department department, BindingResult bindingResult) { 
     if (!bindingResult.hasErrors()) { 
      departmentDao.save(department); 
      return Result.newInstance().setContent(department); 
     } 
     throw new RuntimeException("..."); 
    } 
} 

Есть ли что-нибудь не так?


dao.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/proj 
jdbc.username=root 
jdbc.password= 

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 
hibernate.hbm2ddl.auto=update 
#hibernate.ejb.naming_strategy=true 
hibernate.show_sql=true 
hibernate.format_sql=true 
+1

Почему существуют два аннотации '@ Autowired' и' @ PersistenceContext' над полем 'protected' типа' EntityManager' в 'AbstractJPADao'? – Tiny

+0

'EntityManager' предоставляется в' JpaConfig' как bean-компонент, который должен быть введен в 'AbstractJPADao'. – hguser

+0

В каком контейнере вы работаете? –

ответ

4

Попробуйте метод transactionManager переименований txManager в классе JpaConfig

автоматического связывания выходит под названием txManager

Редактировать

Также инфраструктура может ожидать метод аргументов без аргументов для txManager. Вы можете попытаться изменить к

@Bean 
public PlatformTransactionManager transactionManager() { 
    JpaTransactionManager transactionManager = new JpaTransactionManager(); 
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
    return transactionManager; 
} 
+0

Это не работает. – hguser

+0

@hguser Отредактировал свой ответ. Не могли бы вы попробовать? – gipsy

+0

Спасибо, я попытался: удалить аргументы в методе и использовать как «transactionManager», так и «txManager» в качестве имени метода. Ни один из них не работает. :( – hguser

1

Как заметил Малыш, у вас есть два аннотаций @Autowired и @PersistenceContext над защищаемым полем типа EntityManager в AbstractJPADao. Попробуйте удалить @Autowired. @PersistenceContext достаточно, чтобы ввести EntityManager.

+0

Не исправляет это. – hguser

Смежные вопросы