TransactionRequiredException: Executing an update/delete query
I think if you move the <tx:annotation-driven/>
into the context containing <context:annotation-config/>
, then Spring will pick up your @Transactional
. The <tx:annotation-driven/>
is a post processor that only decorates beans in the application context it is defined in. See my answer here for further explanation.
- Your service class should not also be a repository
- Here is how your applicationContext.xml should look:
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1"/>
<property name="initialSize" value="1"/>
<property name="minIdle" value="1"/>
<property name="maxActive" value="10"/>
<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>
</bean>
- Here is how your unit tests classes should be defined
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=WebContextLoader.class, locations = {"classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-test-override.xml"})
public class MyTest {
- NOTE the use of applicationContext-test-override.xml This is used to override any settings in your context for testing. Doing it this way means you are testing the real application context, so if you make mistakes there, it will come up in your tests. It should be located in src/test/resources. This is all you need hopefully:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="url" value="${database-test.url}"/>
</bean>
- (optional) to use the mode=aspectj
Add the following to the maven plugins. It incorporates aspects at compile time, instead of runtime (mode=proxy).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
<!-- NB: force aspect compile before normal compile, required for 1.3+
see: MASPECTJ-13, MASPECTJ-92 -->
<phase>process-sources</phase>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
I had the some problem and I resolved it by just adding @Transactional annotation on the service method that perform delete or update.
Use this way
@Modifying
@Transactional
@Query(value ="delete from admindata where user_name = :userName AND group_name = :groupName",nativeQuery = true)
public void deleteadminUser(@Param("userName") String userName,@Param("groupName") String groupName);