Hi,
We have an issue where sql statements executed by hibernate are being
immediately committed, despite the fact that the entity manager is managed by a
(local) transaction. It's my understanding that hibernate and the transaction
manager should together ensure that auto commit is disabled on the obtained
connection. My environment is Karaf 4.4.3 on Java 8 and hibernate 5.6.7.
# Here is the persistence.xml file:
<persistence>
<persistence-unit name="acme.pu" transaction-type="JTA" />
</persistence>
# Here is a self-contained class that demonstrates the problem:
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.sql.DataSource;
import org.apache.commons.lang3.RandomStringUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.jdbc.DataSourceFactory;
import org.osgi.service.jpa.EntityManagerFactoryBuilder;
import org.osgi.service.transaction.control.TransactionControl;
import org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory;
import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;
import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;
@Component(immediate = true)
public class AcmeTest {
@Activate
public AcmeTest(
@Reference(target = "(osgi.unit.name=acme.pu)")
EntityManagerFactoryBuilder emfb,
@Reference(target =
"(&(osgi.jdbc.driver.name=oracle)(osgi.jdbc.driver.class=oracle.jdbc.OracleDriver))")
DataSourceFactory dsf,
@Reference(target = "(osgi.local.enabled=true)")
JPAEntityManagerProviderFactory providerFactory,
@Reference(target = "(osgi.local.enabled=true)")
TransactionControl txControl
) throws IOException, SQLException {
// create datasource from factory
Properties dsfProps = new Properties();
dsfProps.put("user", "xxx-withheld-xxx");
dsfProps.put("password", "xxx-withheld-xxx");
dsfProps.put("url", "xxx-withheld-xxx");
DataSource datasource = dsf.createDataSource(dsfProps);
// create jpa entity manager provider from datasource and pool props
Map<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put("javax.persistence.dataSource", datasource);
jpaProperties.put("hibernate.dialect",
"org.hibernate.dialect.Oracle10gDialect");
Map<String, Object> resourceProviderProperties = new HashMap<>();
resourceProviderProperties.put(JDBCConnectionProviderFactory.CONNECTION_POOLING_ENABLED,
false);
JPAEntityManagerProvider provider = providerFactory.getProviderFor(emfb,
jpaProperties, resourceProviderProperties);
// test it out by updating a test_column to a random string
EntityManager entityManager = provider.getResource(txControl);
txControl.required(() -> {
String newValue = RandomStringUtils.random(10, true, false);
Query query = entityManager.createNativeQuery("update test_table set
test_column = ? where test_name = 'test'");
query.setParameter(1, newValue);
query.executeUpdate();
// ***************************************************************
// CONNECTION HAS BEEN COMMITTED SINCE WE CAN SEE
UPDATED VALUE OF
// TEST_COLUMN IN THE DATABASE WHILST WE ARE
STILL IN THIS LAMBDA
// ***************************************************************
return null;
});
}
}
# This information about the transaction services running on the platform might
be important:
admin@root()> bundle:services -p 281
pax-transx-tm-geronimo (281) provides:
--------------------------------------
objectClass = [org.osgi.service.cm.ManagedService]
service.bundleid = 281
service.id = 335
service.pid = org.ops4j.pax.transx.tm.geronimo
service.scope = singleton
----
objectClass = [javax.transaction.TransactionManager,
javax.transaction.TransactionSynchronizationRegistry,
javax.transaction.UserTransaction,
org.apache.geronimo.transaction.manager.RecoverableTransactionManage
r, org.springframework.transaction.PlatformTransactionManager]
service.bundleid = 281
service.id = 360
service.scope = singleton
----
objectClass = [org.ops4j.pax.transx.tm.TransactionManager]
service.bundleid = 281
service.id = 376
service.scope = singleton
admin@root()> bundle:services -p 298
OSGi Transaction Control JPA Resource Provider - Local Transactions (298)
provides:
-----------------------------------------------------------------------------------
objectClass =
[org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory]
osgi.local.enabled = true
service.bundleid = 298
service.id = 312
service.scope = bundle
----
objectClass = [org.osgi.service.cm.ManagedServiceFactory]
service.bundleid = 298
service.id = 313
service.pid = org.apache.aries.tx.control.jpa.local
service.scope = singleton
Thanks
Ash
[EDW Technology]<https://www.teamenergy.com/>
EDW Technology Ltd
3 Radian Court, Knowlhill, Milton Keynes MK5 8PJ, United Kingdom
+44 (0)844 880 2489 | www.edwt.org<https://www.edwt.org>
Energy Auditing Agency Limited (TEAM) registered in England and Wales, number
01916768. Registered office 3 Radian Court, Knowlhill, Milton Keynes MK5 8PJ.
This electronic message contains information which may be privileged or
confidential. The information is intended for the use of the individual(s) or
organisation named. If you are not the intended recipient please be aware that
any disclosure, copying, distribution or use of the contents of this
information is prohibited. If you have received this electronic message in
error, please delete this e-mail from your system and notify us by replying to
this email immediately.