문제

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?

도움이 되었습니까?

해결책 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

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top