Question

I have a method like :

package com.abc.pkg.service.db.impl;



public class OperationServiceImpl extends BaseService implements OperationService {



    @Transactional
        @Override
        public String update(Operation operation,User user) {

        BigDecimal count=(BigDecimal)em.createNativeQuery("select count(*) from RBMCORE.T_RBM_OPSCREENS_OPERATIONS where s_name= ? and id!= ?").setParameter(1, operation.getName()).setParameter(2, operation.getId()).getSingleResult();

        if(count.intValue()>0)
            return "This operation name is used by another operation. Please change it";

        super.removeOpAppRelation(operation.getId(), -1);

        Operation oldOperation=operationRepository.save(operation);
        List<Operation> operations=new ArrayList<Operation>();
        operations.add(operation);
}
}

and the super.insertOpAppRelation method content is:

package com.abc.pkg.service.db.impl;
public abstract class BaseService {


@PersistenceContext
protected EntityManager em;

@Transactional
    protected  void removeOpAppRelation(int opId,int appId){
        String sql="delete table a where 1=1";
        if(opId>0)
            sql+=" and op_id="+opId;

        if(appId>0)
            sql+=" and app_id="+appId;

        em.createNativeQuery(sql).executeUpdate();
    }
}

And removeOpAppRelation method is triggered, this exception is thrown:

javax.persistence.TransactionRequiredException: Executing an update/delete query

and in my appcontext.xml I have these:

<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.abc.pck"/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="rbmDataSource"/>
    <property name="packagesToScan" value="com.ttech.rbm.model"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/>
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="true"/>
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">none</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

As transaction manager, I am using:

org.springframework.orm.jpa.JpaTransactionManager

Any ideas? Is it related with the inheritance?

Was it helpful?

Solution 2

Found it. the entity manager that I have passed into the transaction manager is not AOP safe. because of it, it does not start a transaction while executing a query with it. I have opened and managed my own transaction and problem solved. Thanks for replies

OTHER TIPS

Your code is to much simplified.

The "em" used is not declared in any of your classes.

I would expect an

@PersistenceContext
EntityManager em;

in one of your classes.

If it's in both classes it would explain your error, because in this case two different entity managers will be injected which will not share the same transaction.

To avoid this you should use an abstract method "getEm()" in your superclass and override it in your child class, providing the em injected there.

In addition the @Transactional on the superclass will have no effect when called from the child class, because the super-method it's called directly from the child and not through a spring-aop-proxy - spring has no chance to intercept.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top