I'm trying to execute a query which has to delete items from a sub select.
Environment :
- Wildfly 8.2
- Spring Framework 4.1.6
- Spring Data 1.8.0
- Hibernate 4.3.10
- MySQL 5
Here's the repository :
public interface MySecondEntityRepository extends JpaRepository<MySecondEntity, UUID> {
@Modifying
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Query("DELETE FROM MySecondEntity e WHERE e.uuid IN ("
+ "SELECT e2.uuid "
+ "FROM MySecondEntity e2, MyEntity e1 "
+ "WHERE e2.entityUUID = e1.uuid "
+ "AND e1.uuid = :uuid "
+ "AND e1.*** = ..."
+ "AND e1.*** = ..."
+ ")")
public void deleteByEntityUUID(@Param("uuid") UUID entityUUID, ...);
}
Here's the transaction manager's XML definition :
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
where entityManagerFactory
is a LocalContainerEntityManagerFactoryBean
.
I'm using them not to be dependent of the provider.
In the logs, I can see :
SQL | insert into HT_my_entity select ...
SQL | delete from my_entity where uuid IN (select uuid FROM HT_my_entity);
When I execute manually the select ...
, I get the correct uuids to be deleted. but when spring/hibernate execute them, the transaction does not commit even with Propagation.REQUIRES_NEW
. No exception thrown.
Full logs :
14:41:45,073 | DEBUG | AnnotationTransactionAttri:108 | Adding transactional method 'DefaultJpaRepositoryImpl.deleteByEntityUUID' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; ''
14:41:45,073 | DEBUG | JpaTransactionManager :367 | Creating new transaction with name [xxx.spring.jpa.factory.DefaultJpaRepositoryImpl.deleteByEntityUUID]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; ''
14:41:45,074 | DEBUG | JpaTransactionManager :371 | Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@cd414] for JPA transaction
14:41:45,075 | DEBUG | AbstractTransactionImpl :160 | begin
14:41:45,075 | DEBUG | LogicalConnectionImpl :226 | Obtaining JDBC connection
14:41:45,075 | DEBUG | LogicalConnectionImpl :232 | Obtained JDBC connection
14:41:45,076 | DEBUG | JdbcTransaction :69 | initial autocommit status: true
14:41:45,076 | DEBUG | JdbcTransaction :71 | disabling autocommit
14:41:45,076 | DEBUG | JpaTransactionManager :403 | Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7d7135]
14:41:45,078 | DEBUG | JpaTransactionManager :334 | Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@cd414] for JPA transaction
14:41:45,079 | DEBUG | JpaTransactionManager :417 | Suspending current transaction, creating new transaction with name [xxx.spring.jpa.factory.DefaultJpaRepositoryImpl.deleteByEntityUUID]
14:41:45,082 | DEBUG | JpaTransactionManager :371 | Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@35e880] for JPA transaction
14:41:45,082 | DEBUG | AbstractTransactionImpl :160 | begin
14:41:45,082 | DEBUG | LogicalConnectionImpl :226 | Obtaining JDBC connection
14:41:45,083 | DEBUG | LogicalConnectionImpl :232 | Obtained JDBC connection
14:41:45,083 | DEBUG | JdbcTransaction :69 | initial autocommit status: true
14:41:45,083 | DEBUG | JdbcTransaction :71 | disabling autocommit
14:41:45,084 | DEBUG | JpaTransactionManager :403 | Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1b46a77]
14:41:45,223 | DEBUG | SQL :109 | insert into HT_my_entity select my_second_0_.uuid as uuid from my_second_entity my_second_0_ where my_second_0_.uuid in (select my_second_1_.uuid from my_second_entity my_second_1_ cross join my_entity my_entity_2_ where my_second_1_.entity_uuid=my_entity_2_.uuid and my_entity_2_.uuid=?)
14:41:45,232 | DEBUG | SQL :109 | delete from my_entity where uuid IN (select uuid FROM HT_my_entity);
14:41:45,333 | DEBUG | JpaTransactionManager :755 | Initiating transaction commit
14:41:45,334 | DEBUG | JpaTransactionManager :512 | Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@35e880]
14:41:45,335 | DEBUG | AbstractTransactionImpl :175 | committing
14:41:45,388 | DEBUG | JdbcTransaction :113 | committed JDBC Connection
14:41:45,389 | DEBUG | JdbcTransaction :126 | re-enabling autocommit
14:41:45,393 | DEBUG | JpaTransactionManager :600 | Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@35e880] after transaction
14:41:45,394 | DEBUG | EntityManagerFactoryUtils :432 | Closing JPA EntityManager
14:41:45,396 | DEBUG | LogicalConnectionImpl :246 | Releasing JDBC connection
14:41:45,397 | DEBUG | LogicalConnectionImpl :264 | Released JDBC connection
What I tried :
Propagation.REQUIRED
andPropagation.REQUIRES_NEW
.flush()
after the method's call- Unwrap the subquery to test it. It works correctly.
- Update Spring Data / Hibernate
Note :
- I do not include
MySecondEntity
inMyEntity
for performance reason. AMyEntity
can have 10k+MySecondEntity
. I know I can use lazy fetching but actually, entities are mapped to data transfert object and this cause issues to mapping process. Also, I do not want the retrieve all the data to delete them. <tx:annotation-driven/>
is defined<aop:aspectj-autoproxy/>
is defined- The method is called directly from a
@RestController
.