I am opening transaction using TransactionInterceptor and using HibernateTransactionManager and com.zaxxer.hikari.HikariDataSource as datasource.
I have set autocommit value for datasource and hibernate property hibernate.connection.provider_disables_autocommit values as follows
<property name="autoCommit" value="false"/>
<prop key="hibernate.connection.provider_disables_autocommit">true</prop>
Even then the transaction is getting opened much before it is required.
5.3.1.Final version of hibernate-core is used for the above.
I have used the following references.
https://github.com/spring-projects/spring-boot/issues/9261
https://vladmihalcea.com/why-you-should-always-use-hibernate-connection-provider_disables_autocommit-for-resource-local-jpa-transactions/
Please let me know in case anything else was required to be done or what is the exact meaning of delay.
Thanks in advance.
Apart from configuring autocommit as false in hibernate as you did, you also need to set autocommit to false at the connection pool level. Otherwise, it won't be effective as in your case. Say, for Hikari pool you need to configure as below:
HikariConfig hikariConfig = super.hikariConfig( dataSource );
hikariConfig.setAutoCommit( false );
Related
I have this hibernate.transaction.manager_lookup_class property in my persistence.xml, Then i have this warning message when running my application.
Using deprecated org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class], use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead [hibernate.transaction.jta.platform]
I don't know what is the different between the 2 properties ? And what is the use of them ?
Could anyone explain the difference and the use of them
I'm using hibernate 4 with websphere 8.5
The JtaPlatform offers more transaction-like integrations besides just the transaction manager, notably:
how to locate transaction manager
how to user transaction
how to register transaction synchronization
You can see the full JtaPlatform interface on GitHub here: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/spi/JtaPlatform.java
Replace the following:
<property name = "hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
with
<property name = "hibernate.transaction.jta.platform" value ="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
in the Hibernate configuration/persistence.xml.
I just started learning Hibernate, but based on the reading I have done in the manual, the below code appears to be using auto-commit as commit() is not being explicitly called. All of the examples I found here show use of commit(). Since I am just learning I wanted to get confirmation from the community that I was thinking the right way.
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
session.clear();
entityReturned = (MultipleKeyTable) session.get(MultipleKeyTable.class, entityId);
session.close();
Edit
I should have mentioned that the hibernate.connection.autocommit is not defined in config and I believe that by default it is set to true.
Edit
I was wrong hibernate.connection.autocommit is set to false by default. Thanks Apostolos .
You can setup the autocommit mode at hibernate via hibernate.connection.autocommit
property
please read the configuration documentation
Based on your updated question, you are not using autocommit since you didnt specify the autocommit in your configuration. You are also making a select query, so you wont see if something happens in your db. make some changes, save them and then check again.
You need to commit your transaction in order to save the changes, or define autocommit = true at your properties.
I am using a library where I need to get a data source and feed it into it. is there anyway I can get a connection from a connection pool? I am using Hibernate 4 with C3p0 connection pool.
here is my hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/sampleDB</property>
<property name="connection.username">root</property>
<property name="connection.password">mypass</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="c3p0.max_size">100</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.idle_test_period">30</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- Shows Generated SQL Queries By Hibernate -->
<property name="show_sql">false</property>
<!-- Drop and re-create The Database Schema on Start up -->
<property name="hbm2ddl.auto">update</property>
<property name="cache.provider.class">org.hibernate.cache.NoCacheProvider</property>
</session-factory>
</hibernate-configuration>
If you are using hibernate and you want access to the c3p0 Connection pool it is already using , one easy approach would be to use the C3P0Registry class to find the DataSource, see here and here.
Probably you will find that getPooledDataSources() returns a Set containing single element, and that will be the DataSource hibernate has constructed. If you want to, you can also set the config param c3p0.dataSourceName (hibernate.c3p0.dataSourceName in hibernate config), and use C3P0Registry.pooledDataSourcesByName( dataSourceName ).
[If you will set your own name, it would probably be worth verifying that hibernate is not using the dataSourceName property itself. I don't think that it does, but I haven't checked. The easiest way to check would be to look at your logs for the pools config dump on init, and make sure that there's something like "dataSourceName -> z8kflt8uqkl8iymaxxkw|729f44" in it. If the name is a long random-ish String with a pipe in it, it's an instance-specific autogenerated identity token and you should feel free to set your own name. If you see a more sensible name, then hibernate has already set this property and may be expecting the name you see, so you should look up that name.]
Note that if you plan to use Connections from the DataSource directly, take care to ensure that all Connections get properly close()ed in finally blocks. If you "leak" Connections, i.e. if you check them out and fail to check them back in reliably, you'll eventually exhaust the pool and freeze your hibernate app.
Good luck!
Update: Example...
import java.util.Set;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.C3P0Registry;
// you probably want better Exception handling than this...
private DataSource findUniqueDataSource()
{
Set set = C3P0Registry.getPooledDataSources();
int sz = set.size();
if ( sz == 1 ) // yay, just one DataSource
return (DataSource) set.iterator().next();
else
throw new RuntimeException("No unique c3p0 DataSource, found:" + sz);
}
// be sure you have configured a dataSourceName in your c3p0 or hibernate config
private DataSource findDataSourceByName( String dataSourceName )
{ return C3P0Registry.pooledDataSourceByName(dataSourceName); }
And no, you should not "leak" Connections and expect the pool to clean up after you. You can forget to close Statements and ResultSets, and the pool will take care of them when you close() the Connection, but the pool doesn't know when it's safe to snatch a Connection back from a client that has failed to close it. Some applications hold Connections open for a long time (although that's bad practice, if you are using a Connection pool).
You can force c3p0 to clean up leaked Connections after a period of time, see the config parameter unreturnedConnectionTimeout. But this is an icky strategy; I recommend if you have a leak to use this in concert with debugUnreturnedConnectionStackTraces only temporarily, to understand where you are leaking Connections and then fix the problem.
c3p0 provides connection pool for Hibernate, as The built-in Hibernate connection pool is in no way intended for production use. It lacks several features found on any decent connection pool - According to Hibernate Community Documentation, for configuration of c3p0 with Hibernate you can refer to this or MKYong tutorial on Hibernate Community.
It looks to me as though support for multi tenancy has been added to hibernate for nearly six months now and updated at least once since.
It looks fairly trivial to obtain a multi-tenant Session outside of JPA:
Session session = sessionFactory.withOptions().tenantIdentifier( "jboss" ).openSession();
But how would you enable it in an application that uses hibernate via JPA? (If possible).
Thanks in advance.
You can configure it via properties in persistence.xml as follows:
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.multi_tenant_connection_provider" value="com.example.MyConnectionProvider" />
<property name="hibernate.tenant_identifier_resolver" value="com.example.MyTenantIdResolver" />
If you use SCHEMA as multi-tenancy strategy hibernate.multi_tenant_connection_provider is not needed.
You can also set these properties in your code and pass them in a map to Persistence.createEntityManagerFactory(). In this case you can pass an object instance, not just a class name.
More info in Hibernate documentation.
EntityManager.getDelegate() will return underlying SessionImpl.
I'm trying to use a JDBC Job Store in Quartz with the following code:
DateTime dt = new DateTime().plusHours(2);
JobDetail jobDetail = new JobDetail(identifier, "group", TestJob.class);
SimpleTrigger trigger = new SimpleTrigger(identifier, dt.toDate());
trigger.setJobName(identifier);
trigger.setJobGroup("group");
quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);
And am configuring the scheduler as follows:
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
<property name="autoStartup" value="true" />
<property name="waitForJobsToCompleteOnShutdown" value="false" />
<property name="dataSource" ref="schedulerDataSource" />
<property name="nonTransactionalDataSource" ref="nonTXdataSource" />
<property name="quartzProperties">
<props>
<!--Job Store -->
<prop key="org.quartz.jobStore.driverDelegateClass">
org.quartz.impl.jdbcjobstore.StdJDBCDelegate
</prop>
<prop key="org.quartz.jobStore.class">
org.quartz.impl.jdbcjobstore.JobStoreCMT
</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
</props>
</property>
</bean>
The schedulerDataSource is a standard JNDI data source, the nonTXdataSource is configured via a simple org.springframework.jdbc.datasource.DriverManagerDataSource I have specified the job store class to be: org.quartz.impl.jdbcjobstore.JobStoreCMT and was hoping that the code:
quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);
would not commit the job to the database when the each method is called. Basically when I call addJob the job is immediately saved to the database, the scheduleJob method causes the trigger information to be immediately saved in the database as well, but this tends to happen over two separate transactions already.
There is a fair bit of subsequent logic in the code that needs to be committed to the database together with the scheduled jobs in one transactions, however no matter what I try the jobs are committed by the scheduler to the database as soon as they methods are called. I tried in various environments Testing/Tomcat/Glassfish and various configurations of data sources but to no avail.
Can somebody point me into the direction of where I am going wrong?
Thank you.
Having thought this over a bit, now i believe you can achieve this providing your own wrapping DataSource but you should not do this. I think Quartz maintains some internal state in memory that must be in sync with the database (or at least it can do so). If you rollback a transaction or otherwise modify database state not notifying Quartz about this fact, it may not work as expected.
On the other hand you can use Quartz's pausing of the jobs to achieve similar effect: you simply create new job and pause it before adding any triggers. Then, you resume it only after you commit your transaction.
---------------------- my original answer ----------------------
I think, but I'm not sure, not tried this, that you can try the following:
You need a transaction around a code that uses DataSource.getConnection internally. To achieve that you have to use data source that'd be aware of global transaction state. I suppose that JBoss application server gives you just that (even with plain data source).
JBoss comes with a transaction manager (Arjuna) and data sources wrappers (JBoss app server internal) that are at least aware of global transaction state.
Other options include Atomikos and a XA data source, but i have less experience here.
Edit: if Quartz uses explicit COMMIT or setAutocommit(true) internally, both my suggestions would not work.
When you set datasource on SchedulerFactoryBean, spring uses below class as JobStore ( extension to Quartz's JobStoreCMT )
LocalDataSourceJobStore
This supports both transactional and non-transactional DataSource access.
Please try following
Remove property org.quartz.jobStore.class [Edit : Its ignored ,anyways]
Make sure the method which does addJob / ScheduleJob is in spring managed transaction.