Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not save/update entity using JPA in spring

I am using JPA in my application, and it works once I query for objects, however it throw error javax.persistence.TransactionRequiredException: No transactional EntityManager available once I tried to save or update an object.

This is the java configuration:

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

Note I use proxyTargetClass = true in the @EnableTransactionManagement, since I do not want to create the useless interfaces in my application.

And this is the concrete implemention of the dao:

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

And the controller as the client of the 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("...");
    }
}

Is there anything wrong?


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
like image 590
hguser Avatar asked Sep 14 '15 02:09

hguser


People also ask

Does Save update JPA?

You can choose between JPA's persist and merge and Hibernate's save and update methods. It seems like there are 2 pairs of 2 methods that do the same. You can use the methods persist and save to store a new entity and the methods merge and update to store the changes of a detached entity in the database.

Which method is used to update entity in JPA?

We use the EntityManager. merge() method to update an entity. This method takes the entity to be saved as the parameter and return the merged entity back as the result.

Which method is used for update in JPA Repository?

You can modify or update the entities by defining the repository method using @Query and @Modifying annotations. All the update/delete operations are based on the transaction scope.


2 Answers

Try renaming method transactionManager to txManager in the class JpaConfig

Autowiring goes by the name txManager

Edit

Also the framework could be expecting a no argument method for txManager. Can you try changing to

 @Bean
 public PlatformTransactionManager transactionManager() {
     JpaTransactionManager transactionManager = new JpaTransactionManager();
     transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
     return transactionManager;
 }
like image 90
gipsy Avatar answered Oct 05 '22 04:10

gipsy


As noticed Tiny, you have two annotations @Autowired and @PersistenceContext over the protected field of type EntityManager in AbstractJPADao. Try removing @Autowired. @PersistenceContext is enough to inject the EntityManager.

like image 23
Adrien Colson Avatar answered Oct 05 '22 04:10

Adrien Colson