1

I am migrating my code from hibernate 3 (that is using hibernate template) to JPA 2. My project is using Spring as well.

Current project is using hibernatetempate as

hibernateTemplate.executeWithNativeSession(new HibernateCallback<Object>() {
            @Override
            public Object doInHibernate(Session session) throws SQLException {
                Query query = session.getNamedQuery("updateToProcessed");
                query.setParameter("Id", id);
                return query.executeUpdate();
            }
        });

updateToProcessed is a simple update hql query. Please help to let me know how to convert it to JPA (to use entityManager)

I tried using

Query query = entityManager.createNamedQuery("updateToProcessed");
        query.setParameter("Id", id);
        query.executeUpdate();

Complete method is

@Override
    public void updateAllBatchDetails(final String id) {
            Query query = entityManager.createNamedQuery("updateToProcessed");
            query.setParameter("Id", id);
            query.executeUpdate();
    }

But I am getting error as:

Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:333)
    at com.sun.proxy.$Proxy143.executeUpdate(Unknown Source)

I have configured transactionManager in applicationContext.xml like

I was expecting this answer and I have already configured that in applicationContext.xml but still I am getting that error

<tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory"/>

But somehow @Transactional is working that I don't want to use.

This is the applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <context:component-scan base-package="com.batch"/>
    <context:annotation-config/>
    <context:spring-configured/>

    <context:property-placeholder location="classpath:batch.properties"/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory"/>

    <aop:aspectj-autoproxy/>

    <import resource="classpath:core/applicationContext.xml"/>
    <import resource="classpath:spring/applicationContext-resources.xml"/>
    <import resource="classpath:spring/applicationContext-batch.xml"/>


    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:persistenceUnitName="default"
          p:jpaVendorAdapter-ref="jpaVendorAdapter"
          p:dataSource-ref="dataSource" />

    <bean id="batchProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
          p:location="classpath:batch.properties"/>


</beans>
Vik
  • 125
  • 1
  • 9
  • The error indicates that you haven't setup transactions properly. Make sure that you have the `JpaTransactionManager` configured and that you have marked the methods you want transactional as transactional, either with `@Transactional` and `` or using a `` and `` element. – M. Deinum Sep 09 '14 at 05:40
  • I was expecting this answer and I have already configured that in applicationContext.xml but still I am getting that error But somehow @Transactional is working that I don't want to use – Vik Sep 09 '14 at 06:56
  • The fact that you configured it doesn't mean it is correct. Judging from the stacktrace it isn't. My guess you have a component-scan and scanning for the same beans twice, leading to a proxied and unproxied instance. – M. Deinum Sep 09 '14 at 08:18
  • checked it again and confirming that component-scan is done once only. – Vik Sep 10 '14 at 01:01
  • make sure that you are scanning in the same context as the `` is in, else transactions won't be applied. Also make sure that, although you might have a single component-scan, the configurationi s only loaded once and not twice. – M. Deinum Sep 10 '14 at 06:17
  • You are only posting snippets please post some full configuration, stacktraces including the web.xml and which files are loaded by the `ContextLoaderListener` and which are loaded by the `DispatcherServlet`. Trust me you are scanning or constructing objects twice somewhere else transactions would have been applied. I also assume you use hibernate you aren't messing around with the `hibernate.current_session_context` property are you? – M. Deinum Sep 11 '14 at 05:46

2 Answers2

0

To execute a bulk update you should do like below:

final String updateQuery = "update Person p SET p.name = 'Other Name'";
final int update = entityManager.createQuery(updateQuery).executeUpdate();
System.out.println("updated rows " + update);

Spring will handle the commit for you. [=


Edit: Caused by: javax.persistence.TransactionRequiredException

Have you configured the Transaction? To execute a update you must open a transaction.

With Spring you could use the annotation @Transactional in the method.

uaiHebert
  • 1,882
  • 11
  • 21
  • Thanks for that. I already tried that in this way: Query query = entityManager.createNamedQuery("updateToProcessed"); query.setParameter("id", Id); query.executeUpdate(); But it is giving me the error: Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71) – Vik Sep 09 '14 at 04:07
  • Edited the question again. Added the transactionManager configuration but not working with configuration. – Vik Sep 09 '14 at 06:59
  • Could you post the method that is using the EntityManager? – uaiHebert Sep 09 '14 at 17:42
  • edited the question. Method was already posted without signature but now the complete method is posted. – Vik Sep 10 '14 at 01:06
  • Take a look at the edit in my comment, you need to annotate it with @Transactional – uaiHebert Sep 10 '14 at 02:10
  • but if transaction config is there, it should work. I posted the config. Just want to know why that is not working? – Vik Sep 10 '14 at 23:31
  • Where did you see that it should work only with the transaction config? I believe that this would be a wrong behavior, imagine that for every incoming request a new transaction would be opened in the controller. You need to tell the Spring where you want an active transaction. – uaiHebert Sep 10 '14 at 23:43
  • I am doing that with all jpa using transactional anootation with read only false and then update with readonly true. thanks for all your suggestions. – Vik Sep 30 '14 at 23:05
0

For this problem use a Tasklet where you execute your query.
Configure a step using a TaskletStep and you can set 'transaction manager' as well as 'transaction attributes' and errors should go away.

Luca Basso Ricci
  • 17,829
  • 2
  • 47
  • 69
  • Thanks for that. But finding it too much complex to do that. I am using it as a decider in decision with some if else condition. – Vik Sep 09 '14 at 07:04