【问题标题】:Can not save/update entity using JPA in spring春季无法使用 JPA 保存/更新实体
【发布时间】:2015-09-14 02:16:50
【问题描述】:

我在我的应用程序中使用 JPA,一旦我查询对象,它就可以工作,但是一旦我尝试保存或更新对象,它就会抛出错误 javax.persistence.TransactionRequiredException: No transactional EntityManager available

这是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;
    }
}

注意我在@EnableTransactionManagement 中使用proxyTargetClass = true,因为我不想在我的应用程序中创建无用的接口。

这是道的具体实现:

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

而控制器作为dao的客户端:

@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

【问题讨论】:

  • 为什么AbstractJPADaoprotected类型为EntityManager的字段有两个注解@Autowired@PersistenceContext
  • EntityManagerJpaConfig 中作为bean 提供,应该注入AbstractJPADao
  • 你在什么容器中运行?
  • 不知道这是否是您的问题,但使用org.springframework.transaction.annotation.Transactional 而不是javax.transaction.Transactional 注释解决了另一个类似问题。
  • 我现在用的是tomcat,我更喜欢使用标准的注解。

标签: java spring jpa spring-data-jpa


【解决方案1】:

尝试将JpaConfig类中的方法transactionManager重命名为txManager

Autowiring 的名字是 txManager

编辑

此外,框架可能期望 txManager 的无参数方法。可以试试改成

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

【讨论】:

  • @hguser 编辑了我的答案。可以试试吗?
  • 谢谢,我试过了:去掉方法中的参数,同时使用'transactionManager'和'txManager`作为方法名。它们都不起作用。 :(
  • @hguser 到目前为止,一切都只是我的猜测。今天有时间我要试一试自己的样品。如果在我的实验之前没有人回答你的问题,我会在这里发布我的发现来帮助你解决这个问题。
  • 谢谢,正在寻找您的实验。
  • 顺便说一句,我已经将我的原型项目更新为bitbucket,如果你有帐户,我可以邀请你分叉项目。
【解决方案2】:

正如 Tiny 所注意到的,您在 AbstractJPADao 中的 EntityManager 类型的受保护字段上有两个注释 @Autowired 和 @PersistenceContext。 尝试删除@Autowired。 @PersistenceContext 足以注入 EntityManager。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 2016-12-04
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多