Spring/Hibernate #Transactional on method prevents update SQL - spring

Spring v4.2.5 Release
Hibernate v5.1.0.Final
I have a Junit test method which performs a load, updates a property and calls saveOrUpdate(bean).
It's behaving oddly in that adding #Transactional to the method signature prevents the update SQL from being performed (No SQL generated in log).
Remove the #Transactional and the update SQL is generated and the database updated.
#Configuration
#EnableTransactionManagement
#PropertySource(
{
"classpath:jdbc.properties",
"classpath:hibernate.properties"
})
#ComponentScan(value = "com.savant.test.spring.donorservice.core.dao")
public class ApplicationContext {
#Bean(destroyMethod = "close")
#Autowired
public DataSource dataSource() {
// Hikari is a connection pool manager.
HikariDataSource dataSource = new HikariDataSource();
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
dataSource.setJdbcUrl(env.getProperty("jdbc.url"));
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setIsolateInternalQueries(true);
System.out.println(dataSource);
dataSource.setConnectionTestQuery("SELECT count(*) from system.onerow");
dataSource.setMaximumPoolSize(3);
dataSource.setAutoCommit(false);
return dataSource;
}
#Bean
#Autowired
public LocalSessionFactoryBean sessionFactory(DataSource datasouce) {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(datasouce);
sessionFactory.setPackagesToScan(package_to_scan);
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put(hibernate_dialect, env.getProperty(hibernate_dialect));
hibernateProperties.put(hibernate_current_session_context_class, env.getProperty(hibernate_current_session_context_class));
hibernateProperties.put(hibernate_connection_autocommit, env.getProperty(hibernate_connection_autocommit));
hibernateProperties.put(hibernate_format_sql, env.getProperty(hibernate_format_sql));
hibernateProperties.put(hibernate_hbm2ddl_auto, env.getProperty(hibernate_hbm2ddl_auto));
hibernateProperties.put(hibernate_show_sql, env.getProperty(hibernate_show_sql));
// hibernateProperties.put(hibernate_connection_provider_class, env.getProperty(hibernate_connection_provider_class));
return hibernateProperties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager(sessionFactory);
return txManager;
}
The entities have been auto-generated using Netbeans 'Entity classes from Database'.
The main Entity has
A one-to-one relationship with FetchType.EAGER
A one-to-many relationship with FetchType.EAGER (it was LAZY - read below).
The test method looks like this.
#Test
#Transactional
public void c_testUpdateAddress1() {
System.out.println("findById");
String id = donorId;
Donor donor = donorDao.findById(id);
donor.setAbogrp(" O");
for (DonorAddress da : donor.getDonorAddressCollection()) {
da.setAddr1("Updated line");
System.out.println(da.getDonorAddressPK().getAddrtype() + " " + da.getAddr1());
}
System.out.println("Update");
Donor savedDonor = donorDao.save(donor);
}
Without #Transactional The update SQL is generated and the database
is updated.
With #Transactional The update SQL is not generated, does not appear
in the log. There are no exceptions, stepping over the Save method
in my Dao implementation everything appears fine. The bean passed in
has the correct values (updated field values), the bean returned has
the updated field values - just no SQL generated.
#Override
public Donor save(Donor bean) {
getSession().saveOrUpdate(bean);
return bean;
}
The reason I need #Transactional is to allow the address to the LAZY.
Without #Transactional I can't access the address as LAZY due to exception "failed to lazily initialize a collection of role: could not initialize proxy - no Session"

Which is as expected.
A transaction is started as soon as a #Transactional method is detected and committed as soon as that method call ends. Which in the case of a test is after the end of the test method. So during your tests you will not see the SQL.
Also when using #Transactional on a Spring based test it will by default do a rollback instead of a commit. See here in the reference guide on the default and how to change it.

Answer was provided by M Deinum as a comment

Related

Spring Disable #Transactional from Configuration java file

I have a code base which is using for two different applications. some of my spring service classes has annotation #Transactional. On server start I would like to disable #Transactional based on some configuration.
The below is my configuration Class.
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class WebAppConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(url);
dataSource.setUsername(userId);
dataSource.setPassword(password);
return dataSource;
}
#Bean
public PlatformTransactionManager txManager() {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
if(appName.equqls("ABC")) {
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
}else {
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}
CustomDataSourceTransactionManager txM=new CustomDataSourceTransactionManager(def);
txM.setDataSource(dataSource());
return txM;
}
#Bean
public JdbcTemplate jdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource());
return jdbcTemplate;
}
}
I am trying to ovveried methods in DataSourceTransactionManager to make the functionality. But still it is trying to commit/rollback the transaction at end of transaction. Since there is no database connection available it is throwing exception.
If I keep #Transactional(propagation=Propagation.NEVER), everything works perfectly, but I cannot modify it as another app is using the same code base and it is necessary in that case.
I would like to know if there is a to make transaction fully disable from configuration without modifying #Transactional annotation.
I'm not sure if it would work but you can try to implement custom TransactionInterceptor and override its method that wraps invocation into a transaction, by removing that transactional stuff. Something like this:
public class NoOpTransactionInterceptor extends TransactionInterceptor {
#Override
protected Object invokeWithinTransaction(
Method method,
Class<?> targetClass,
InvocationCallback invocation
) throws Throwable {
// Simply invoke the original unwrapped code
return invocation.proceedWithInvocation();
}
}
Then you declare a conditional bean in one of #Configuration classes
// assuming this property is stored in Spring application properties file
#ConditionalOnProperty(name = "turnOffTransactions", havingValue = "true"))
#Bean
#Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
/* default bean would be injected here */
TransactionAttributeSource transactionAttributeSource
) {
TransactionInterceptor interceptor = new NoOpTransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
return interceptor;
}
Probably you gonna need additional configurations, I can't verify that right now

Use Spring and EJB transaction together

I am getting the error while try to add the entity into the DB. I have referred this. But it did not have much info regarding my issue
I have one EJB jar which I use to manage the get,save and update the entity.
Here is my remote ejb
#Remote
public abstract interface DatalayerService{
public abstract void add(Object object)
}
Here is the implemetation
#TransactionManagement(TransactionManagementType.CONTAINER)
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class DatalayerServiceImpl implements DatalayerService{
#PersistenceContext(name="myPersistenceUnit")
EntityManager em = null;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void add(Object object) throws FatalException{
try {
em.persist(object);
}
catch (Throwable e){
throw manageDatalayerError(e);
}
finally {
}
}
}
I am trying to use the above ejb in my application
1)
#ComponentScan({"com.springboot"})
#EnableJpaRepositories
#SpringBootApplication
public class SpringEjbApplication extends SpringBootServletInitializer{
public static void main(String args[]){
SpringApplication.run(SpringApplication.class,args);
}
#Bean
public DatalayerService datalayerService() throws NamingException{
return new DatalayerServiceImpl();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException{
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[]{"com.springboot.pojo"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
em.setJpaVendorAdapter(vendorAdapter);
em.setPersistenceUnitName("myPersistenceUnit");
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource() throws NamingException{
return (DataSource) new JndiTemplate().lookup("openejb:Resource/MyDataSource");
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties additionalProperties(){
Properties properties = new Properties();
properties.setProperty("hibernate.max_fetch_depth", "3");
properties.setProperty("hibernate.default_batch_fetch_size", "2");
properties.setProperty("hibernate.jdbc.batch_size", "100");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "false");
return properties;
}
}
2)Rest Service
#RestController
public class HomeEndPoint{
#Autowired
private IUserService iUserService;
#GetMapping("/createUser")
#Transactional(rollbackFor = {ServiceExpectedException.class,FatalException.class,MandatoryParameterMissingFatalException.class})
public void createUser() throws FatalException,ServiceExpectedException{
iUserService.createUser();
}
}
3)User Service and its impl
public interface IUserService{
public void createUser() throws FatalException;
}
#Service
#Transactional(rollbackFor = {ServiceExpectedException.class,FatalException.class,MandatoryParameterMissingFatalException.class})
public class UserServiceImpl implements IUserService{
#Autowired
private DatalayerGenericService datalayerGenericService;
#Override
public void createUser() throws FatalException,ServiceExpectedException{
Team team = new Team(simpleContextService);
team.setGroupName("MyTeam");
team.setStoreId(100);
// Team
datalayerGenericService.add(team);
Log.info(this,"add team ");
// Build user1
datalayerGenericService.add(user1);
Log.info(this,"############################# Added User1 ######################################");
// Build user2
datalayerGenericService.add(user2);
Log.info(this,"############################# Added User2 ######################################");
}
}
I tried to run the rest service with url
http://localhost:6180/SpringBootDatalayer/createUser
I am getting the below exception.
INFO: (com.edifixio.springboot.service.impl.UserServiceImpl)
####################### teamOid 20 INFO: (com.edifixio.springboot.service.impl.UserServiceImpl)
####################### Added User1 ##################################### INFO: (com.edifixio.springboot.service.impl.UserServiceImpl)
####################### Added User2 ##################################### INFO : http-nio-6180-exec-1 : AbstractBatchImpl.release : HHH000010: On release of batch it still
contained JDBC statements 2018-03-27 16:28:17,683 : ERROR :
http-nio-6180-exec-1 : BatchingBatch.performExecution : HHH000315:
Exception executing batch [java.sql.BatchUpdateException: Batch entry
0 insert into TEAM (CREATE_TIMESTAMP, PROJECT_GROUP_NAME,
LAST_UPDATE_TIMESTAMP, STORE_ID, ID) values ('2018-3-27
16:28:17.447000 +5:30:0', 'MMA_TEST', '2018-3-27 16:28:17.503000
+5:30:0', 100, 21) was aborted. Call getNextException to see the cause.], SQL: insert into TEAM (CREATE_TIMESTAMP, PROJECT_GROUP_NAME,
LAST_UPDATE_TIMESTAMP, STORE_ID, ID) values (?, ?, ?, ?, ?)
As you can see from the exception It was creating team,user1 and user2 with the use of datalayerGenericService. But tries to executes again to give AbstractBatchImpl.release : HHH000010: On release of batch it still contained JDBC statements.
Here is the exception I got:
java.sql.BatchUpdateException: Batch entry 1 insert into TEAM
(CREATE_TIMESTAMP, PROJECT_GROUP_NAME, LAST_UPDATE_TIMESTAMP,
STORE_ID, ID) values ('2018-3-29 12:9:26.611000 +5:30:0', 'MMA_TEST',
'2018-3-29 12:9:26.836000 +5:30:0', 100, 23) was aborted. Call
getNextException to see the cause.
How do I resolve this issue? Why the query executing twice?
If there is any exception occurs in EJB methods, it should rollback the transaction. But it is not happening
Note : If I remove #Transactional annotation from the service it works fine.
I am using TomEE 7.0.2 server.
Technically you don't insert neither Users nor team. You persist them to PersistenceContext. When your code leaves
#Transactional(rollbackFor = {ServiceExpectedException.class,FatalException.class,MandatoryParameterMissingFatalException.class})
public void createUser()
It has to be commited or flushed or session closed as far as you have marked it as required. It failures on very first insertion (team) because of you didn't have some of any listed above.
And yes - you are using noting from EJB here. In fact you use Hibernate and only #Transactional as Spring service annotation has effect here.
How did I resolve this issue?
I was misunderstood that there is EJB stuff involved here
But #M. Deinum clarified me that here no EJB involved, regardless the fact that I have added those annotations, which means my DatalayerServiceImpl is just a SpringBean.
Adding all those interfaces and annotations doesn't give me anything but added complexity and overhead in code that is silently ignored by Spring (apart from the Transactional as spring does support that).
Coming to my problem I have declared Team In Users class
#ManyToOne(cascade={CascadeType.PERSIST},fetch=FetchType.LAZY)
#JoinColumn(name="TEAM_ID",nullable=false)
#JsonBackReference
private Team team;
While creating the User I was referencing the Created team instance to Users class
I was doing
Team team = new Team(simpleContextService);
team.setGroupName("MMA_TEST");
team.setStoreId(100);
// Team
Long teamOid = datalayerGenericService.updateWithId(team);
Users user1 = new Users(simpleContextService);
...Set other fields
user1.setTeam(team);
As the Team declared as Cascade type Persist inside Users, it was trying to insert the team when persisting the Users.
So I have changed the Cascade type to MERGE. So it was working fine.

How to register hibernate spring entity listeners

I have built an entity listener but have not figured out how to register it so that it will get called. This all runs, and I verified in the debugger that the
registration code executes (apparently successfully) at startup. But the debugger never stops in the listener code.
This is my listener:
public class DirtyAwareListener implements PostLoadEventListener
{
#Override
public void onPostLoad(PostLoadEvent postLoadEvent)
{
if (postLoadEvent.getEntity() instanceof DirtyAware)
{
((DirtyAware)postLoadEvent.getEntity()).commitFields();
}
}
}
and this is the registration component:
#Component
public class HibernateListenerConfigurer
{
#PersistenceUnit
private EntityManagerFactory emf;
#Autowired
private SessionFactory sessionFactory;
#PostConstruct
protected void init()
{
DirtyAwareListener listener = new DirtyAwareListener();
// SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = ((SessionFactoryImpl)sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.POST_LOAD).appendListener(listener);
}
}
Here is how my general Hibernate configuration code generates a session factory:
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(getDataSource());
sessionFactory.setPackagesToScan("com.my.entities");
sessionFactory.setHibernateProperties(getHibernateProperties());
sessionFactory.setEntityInterceptor(new DirtyAwareInterceptor());
return sessionFactory;
Note that the interceptor does work as expected (but unfortunately does not have hooks where I need them.)
To add entity listeners implement org.hibernate.integrator.spi.Integrator. See example https://www.boraji.com/hibernate-5-event-listener-example
I got this working as desired using the Integrator approach as Anton suggested. The link provided in his answer did not provide sufficient information for me to get this to work - I had to reference multiple posts and also do a bit of trial and error. Since I could not find a single post which provided the info, here is how I did it:
The listener code is the same as the above. The Configurer code is not needed - I deleted it. Here is the new Integrator code:
#Component
public class EventListenerIntegrator implements Integrator
{
#Override
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactoryImplementor, SessionFactoryServiceRegistry sessionFactoryServiceRegistry)
{
EventListenerRegistry eventListenerRegistry =
sessionFactoryServiceRegistry.getService(EventListenerRegistry.class);
DirtyAwareListener t = new DirtyAwareListener();
eventListenerRegistry.getEventListenerGroup(EventType.POST_LOAD).appendListener(t);
}
#Override
public void disintegrate(SessionFactoryImplementor sessionFactoryImplementor, SessionFactoryServiceRegistry sessionFactoryServiceRegistry) {}
}
And here is the revised getSessionFactory method on my #Configuration class:
private static SessionFactory sessionFactory = null;
#Bean
public SessionFactory getSessionFactory()
{
if (sessionFactory == null)
{
BootstrapServiceRegistry bootstrapRegistry =
new BootstrapServiceRegistryBuilder()
.applyIntegrator(new EventListenerIntegrator())
.build();
StandardServiceRegistryBuilder registryBuilder =
new StandardServiceRegistryBuilder(bootstrapRegistry);
registryBuilder.applySetting(org.hibernate.cfg.Environment.DATASOURCE, getDataSource());
registryBuilder.applySettings(getHibernateProperties());
StandardServiceRegistry registry = registryBuilder.build();
MetadataSources sources = new MetadataSources(registry).addPackage("com.my.entities");
sources.addAnnotatedClass(User.class);
Metadata metadata = sources.getMetadataBuilder().build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
}
return sessionFactory;
}
Note: I think the addPackage call is not needed and does not do anything. I had hoped it would do the package scan the old code was doing, but it does not do that. I simply changed that to explicity add each annotated class.

Override Default Datasource getConnection()

I am trying to convert a Spring application (for the most part) to a Spring Boot application. In the app, I have an HTTP basic filter that collects a username and password, this is then passed as variables in a DataSource implementation.
In this DataSource, the getConnection() method is so:
#Override\n public Connection getConnection() throws SQLException {
Statement stmt = null;
try {
ConnectionWrapper connection = this.authenticatedConnection.get();
if (connection == null) {
connection = new ConnectionWrapper(this.dataSource.getConnection());
StringBuilder command;
// The CONNECT command allows indicating a user name, a password
// and a database to initiate a
// new session in the server with a new profile.
command = new StringBuilder("CONNECT USER ").append(this.parameters.get().get(USER_NAME)).append(" PASSWORD ")
.append("'").append(this.parameters.get().get(PASSWORD_NAME)).append("'").append(" DATABASE ")
.append(this.parameters.get().get(DATA_BASE_NAME));
this.authenticatedConnection.set(connection);
stmt = connection.createStatement();
stmt.execute(command.toString());
}
return connection;
} catch (final SQLException e) {...`
(With \n as a new line due to StackOverflow formatting issues)
In Spring, I am able to implement #Autowired Private DataSource dataSource without a problem. In Spring Boot, as I understand it, the Object needs to be a Bean to use #Autowired, but when I add #Bean before this implemented DataSource I get "The annotation #Bean is disallowed for this location"
How can I get it so that I can do a dataSource.getConnection(); and get a connection from the primary DataSource, or be able to Override the methods of the primary DataSource?
The way I see it, there are 4 possible solutions listed here in order of preference:
Create a DataSource that is actually overwriting the spring.datasource' methods.
Get this implementation "Beanified" so I can just #Autowired the dataSource again.
I think I can skip the #Autowired and simply set this.dataSource = [unknown reference to spring.datasource defined in application.properties]
Create another DataSource class ProgrammedDataSource configured with the spring.datasource properties, then set it as this.dataSource = new ProgrammedDataSource();
but my attempts at implementing any of these solutions have produced this question.
I figured it out. I didn't need to make the Bean there, although I am still not sure why I was not allowed to call #Bean before the DataSource, but regardless.
In the application I had:
public class ServiceApplication {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
#Bean(name="AuthDataSource")
public DataSource authDataSource() {
return new AuthDataSource();
}
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
and in the controller I had:
#Controller
#RequestMapping("/service")
public class ServiceController {
#Autowired
public void MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = new JdbcTemplate(new AuthDataSource());
} ...
However, since I was calling new AuthDataSource() inside that JdbcTemplate, it was not doing the Autowiring. Now the Controller looks like this and it works:
#Controller
#RequestMapping("/service")
public class ServiceController {
#Autowired
#Qualifier("AuthDataSource")
private DataSource datasource;
private JdbcTemplate jdbcTemplate;
#Autowired
public void MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
} ...

InvalidDataAccessApiUsageException: Executing an update/delete query Spring XML to Java config

I'm trying to convert spring xml configuration to java configuration. This works perfectly through XML configuration. However, it throws the following exception if I use java config initializer. This happens when it tries to run JQL. The application starts properly though (with all JPA mapping initialized).
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:410) [spring-orm-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:216) [spring-orm-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) [spring-orm-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslat
Following is my persistence initializer class. Bit of reading suggested me this is related to transactions are not being started properly. I've put debug points to each of these methods but transactionManager method never gets executed during server startup or any later time. I'm not sure what am I doing wrong :(. Same code based works perfectly when persistence is initialized through persistence.xml.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "au.mypkg")
public class DatabaseConfig {
#Bean(name = "dataSource")
#Primary
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:jboss/datasources/mydb");
}
#PersistenceContext(unitName = "persistenceUnit")
#Primary
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception {
..........
#Primary
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
final JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setTransactionManagerName(JBOSS_TRANSACTION_MANANGER);
return transactionManager;
}
Error occurs when accessing this method on Dao
public void updateById(final Long id) {
final String sqlQuery = "UPDATE testtable w SET w.LAST_ACCESSED = :date WHERE w.testtable_ID = :testid";
final Query query = dao.createNativeQuery(sqlQuery);
query.setParameter("date", new Date());
query.setParameter("testid", id);
query.executeUpdate();
}
I had the some problem and I resolved it by just adding #Transactional annotation on the service method that perform delete or update.
In my case it was a method that call a repository method which execute a delete by jpql like this by I think it can solve you problem too:
#Modifying
#Query("delete from OtherPayment otherPayment " +
"where otherPayment.otherPaymentParam.id = :otherPaymentParamId")
void deleteByOtherPaymentParamId(#Param("otherPaymentParamId") Long otherPaymentParamId);
Finally figured out what was going on with it. The reason this wasn't hitting the debug point was, EnableTransactionManagement imposes to auto-configure transactions for you. So if your transaction manager configured with default name which is in my case, it wouldn't try to call my method to configure transactions. The only way to get around with this is to use a different name for your transaction manager and pass that ref as a parameter on enableJPARepositories annotation.If you use one of the default names, it wouldn't make this call.
#Primary
#Bean(name = "myRealTransactionManager")
public PlatformTransactionManager transactionManager() {
final JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setTransactionManagerName(JBOSS_TRANSACTION_MANANGER);
return transactionManager;
}
.. and then
#EnableJpaRepositories(basePackages = "au.mypkg", transactionManagerRef = "myRealTransactionManager"
The other problem was I have had used setdatasource as opposed to setJtaDataSource on LocalContainerEntityManagerFatoryBean.

Resources