Issue setting FlushMode.COMMIT in Quarkus Hibernate ORM - java

Issue I have using Quarkus+Hibernate:
For performance purposes we need to set FlushMode as COMMIT in our hibernate Session.
And we realized that this property configuration is not available in application.properties parameters, see: https://quarkus.io/guides/hibernate-orm#hibernate-configuration-properties
So, we took the path to setting up the configuration with persistence.xml file: https://quarkus.io/guides/hibernate-orm#persistence-xml
...
<persistence-unit name="SomethingPU" transaction-type="JTA">
<description>Something Entities</description>
<properties>
<!-- Connection specific -->
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />
<!-- cache properties -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_minimal_puts" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<!-- multitenancy -->
<property name="hibernate.multiTenancy" value="DATABASE" />
<!-- scan for annotated classes -->
<property name="hibernate.archive.autodetection" value="class"/>
<!-- performance tunning -->
<property name="org.hibernate.flushMode" value="COMMIT" />
<property name="hibernate.jdbc.batch_size" value="100" />
<property name="hibernate.jdbc.fetch_size" value="400" />
<property name="hibernate.order_updates" value="true" />
<property name="hibernate.order_inserts" value="true" />
<property name="hibernate.max_fetch_depth" value="1" />
</properties>
</persistence-unit>
When we start our service everything's fine, the properties are loaded into the Session, except for "org.hibernate.flushMode" parameter.
Debugging the code we see this behaviour:
when the service starts, Quarkus executes the Recorder: io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder
this class initialize org.hibernate.Session using the class: io.quarkus.hibernate.orm.runtime.TransactionSessions
TransactionsSessions mantains a Map of io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession
so, when TransactionScopedSession acquires the Session, it executes:
TransactionScopedSession.aquireSession
line 88:
Session newSession = jtaSessionOpener.openSession();
which ends calling JTASessionOpener.createOptions method:
return sessionFactory.withOptions()
.autoClose(true) // .owner() is deprecated as well, so it looks like we need to rely on deprecated code...
.connectionHandlingMode(
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION)
.flushMode(FlushMode.ALWAYS);
Here JTASessionOpener is setting flushMode as ALWAYS
calling the method: SessionFactoryImpl.flushMode
When org.hibernate.internal.SessionImpl is created
org.hibernate.internal.SessionImpl.SessionImpl(SessionFactoryImpl, SessionCreationOptions)
line 266:
if ( getHibernateFlushMode() == null ) {
final FlushMode initialMode;
if ( this.properties == null ) {
initialMode = fastSessionServices.initialSessionFlushMode;
}
...
The method getHibernateFlushMode() is returning FlushMode.ALWAYS
And because of this, the parameter "org.hibernate.flushMode" from persistence.xml is never setted.
We fix this issue setting the flushMode directly in javax.persistence.EntityManager instance, before we use it in any query or DB operation.
But, my questions are:
is there a way to bypass JTASessionOpener or use another logic? can it be considered as a bug or issue to solve?
is there a better way (than our solution) to fix this issue?
is there a plan to add the property "org.hibernate.flushMode" in Quarkus Hibernate ORM extension?, so we can set this in application.properties
--
Hope the description is clear.

Related

How to clear / refresh the cache in EclipseLink

I'm using following settings in persistence.xml (I use Eclipselink 2.6.4) from my web application:
<properties>
<property name="eclipselink.jdbc.cache-statements" value="true" />
<property name="eclipselink.cache.query-results" value="true" />
<property name="eclipselink.ddl-generation.index-foreign-keys" value="true" />
<property name="eclipselink.logging.level" value="OFF" />
<property name="eclipselink.persistence-context.close-on-commit" value="true" />
<property name="eclipselink.persistence-context.flush-mode" value="commit" />
<property name="eclipselink.persistence-context.persist-on-commit" value="false" />
</properties>
I'm using the #Cacheable(false) annotation to prevent some entities from being cached.
The #Cache annotation doesn't work any more in version 2.6.4.
My question is, is there a possibility to clear the cache globally? Let say every 3 hours?
Thanks
First level cache is enabled by default and you can not disable it. i.e. no settings in your persistence.xml file will disable first level cache.
You can only clear out all the entity manager objects by calling
entityManager.clear()
this will make subsequent queries go to the database (the first time) and then objects are again stored in the cache
In your case you would need to store your entitymanager objects in a register somewhere and have a loop through it every 3 hours to call the clear() function.
You can force each query to go to the database directly by calling
query.setHint("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);

configure max pool size hikaricp hibernate JPA

I'm trying to use hibernate jpa and hikaricp for the CP.
But I have an issue that I dont understand, so either my config is bad ... or I do have something else.
this is the config In have in my persistence.xml file :
<properties>
<!-- SQL -->
<property name="hibernate.dialect" value="org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<!-- HikariCP -->
<property name="hibernate.connection.provider_class" value="com.zaxxer.hikari.hibernate.HikariConnectionProvider"/>
<property name="hibernate.hikari.driverClassName" value="com.mysql.jdbc.Driver" />
<property name="hibernate.hikari.minimumIdle" value="5"/>
<property name="hibernate.hikari.maximumPoolSize" value="30"/>
<property name="hibernate.hikari.maxLifetime" value="150000"/>
<property name="hibernate.hikari.dataSource.user" value="user" />
<property name="hibernate.hikari.dataSource.password" value="password" />
<property name="hibernate.hikari.jdbcUrl"
value="jdbc:mysql://server:3306" />
</properties>
Still I'm having 100+ connections on the database. I thought that using maximumPoolSize it would have limit my number of connections. Is my configuration OK, based on my research it seems ok to me, but before trying to debug elsewhere I want to make sure it is.
Thanks
You must be missing the hibernate-hikari module jar on your classpath. This module is necessary to integrate hibernate with HikariCP
Here is the official documentation

Openjpa lock does not work

In a project with OpenJPA 2.1 and oracle database I use mixed lock mode, which default has optimistic locking but can use pessimistic as well. But it does not work for me as I expected.
So I wrote small test for openjpa locking.
Persistance.xml config:
<properties>
<property name="openjpa.Optimistic" value="false" />
<property name="openjpa.LockManager" value="mixed" />
<!-- <property name="openjpa.LockManager"value="mixed(VersionCheckOnReadLock=true,VersionUpdateOnWriteLock=true)" /> -->
<property name="openjpa.RuntimeUnenhancedClasses" value="unsupported" />
<property name="openjpa.slice.ConnectionDriverName" value="oracle.jdbc.OracleDriver" />
<property name="openjpa.slice.ConnectionURL" value="jdbc:oracle:thin:******" />
<property name="openjpa.slice.ConnectionUserName" value="user" />
<property name="openjpa.slice.ConnectionPassword" value="userpassword" />
<property name="openjpa.jdbc.SynchronizeMappings" value="validate" />
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />
<property name="openjpa.Log"
value="DefaultLevel=INFO, Runtime=INFO, Tool=INFO, SQL=TRACE" />
</properties>
My simple test code:
Configuration config = entityManager.find(Configuration.class, 10025984L);
entityManager.lock(config, LockModeType.PESSIMISTIC_WRITE);
In sql trace is see, that after lock method calling OpenJPA does not execute any additional query to database. Single sql query:
TRACE [Thread-7] openjpa.jdbc.SQL - <t 874198043, conn 1773300146> executing prepstmnt 1809148885 SELECT t0.VERSION FROM Configuration t0 WHERE t0.ID = ? [params=?]
What I do wrong and how can I get lock for one entity instance?
I found soulution. The reason was in JPA settings. I just remove property:
<property name="openjpa.Optimistic" value="false" />
And everything became work fine.

Force JDO full initialization (with datanucleus lib)

I am working on warmup request to minimize my requests latency:
https://developers.google.com/appengine/docs/java/config/appconfig#Warmup_Requests
During that initialization I perform:
PersistenceManager pm = PMF.get().getPersistenceManager();
.. but from the logs I see it doesn't parse all the .jdo files where the class metadata are stored.
They are parsed only the first time I call this function "getObjectById" (for example) ..
Is it possible to force datanucleus to fully read all the metadata in order to be completely ready when the first getObjectById hits the PersistenceManager?
Thank you,
Michele
==============================================================================
UPDATE:
I tried with this persistence.xml file:
<persistence-unit name="my-transaction">
<mapping-file><path-to-first-jdo-file></mapping-file>
<mapping-file><path-to-second-jdo-file></mapping-file>
<mapping-file><path-to-third-jdo-file></mapping-file>
<properties>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
<property name="datanucleus.ConnectionURL" value="appengine"/>
</properties>
</persistence-unit>
that is associated with jdoconfig.xml:
<persistence-manager-factory name="my-transaction">
<property name="javax.jdo.PersistenceManagerFactoryClass" value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory" />
<property name="javax.jdo.option.ConnectionURL" value="appengine" />
<property name="javax.jdo.option.NontransactionalRead" value="true" />
<property name="javax.jdo.option.NontransactionalWrite" value="true" />
<property name="javax.jdo.option.RetainValues" value="true" />
<property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true" />
<property name="datanucleus.appengine.allowMultipleRelationsOfSameType" value="true" />
<property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" />
<property name="datanucleus.appengine.ignorableMetaDataBehavior" value="ERROR" />
<property name="javax.jdo.option.Multithreaded" value="true"/>
<property name="javax.jdo.option.Optimistic" value="false" />
</persistence-manager-factory>
.. but I continue to see in the logs the previuos behaviour. During loading request:
org.datanucleus.store.types.TypeManager addJavaType: Adding support for Java type <class>
.. and during the first request that really needs a class mapping (getObjectById for example):
org.datanucleus.metadata.xml.MetaDataParser parseMetaDataStream: Parsing MetaData file <class>.jdo
So the first request that retrieves the object is longer than the following ones because it needs to parse the XML file.
What's wrong?
I am using datanucleus 1.1.5
Thank you
Specify a "persistence.xml" defining all classes/mapping files. This is then read/loaded at startup.
Also ancient version of DataNucleus aren't supported, so use the newer version of the GAE JPA plugin with DataNucleus v3.x

OpenJPA - not flushing before queries

how can i set openjpa to flush before query. When i change some values in database i want to propagate these changes into application.
I tried this settings in persistence.xml:
<property name="openjpa.FlushBeforeQueries" value="true" />
<property name="openjpa.IgnoreChanges" value="false"/> false/true - same behavior to my case
<property name="openjpa.DataCache" value="false"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm"/>
<property name="openjpa.ConnectionRetainMode" value="always"/>
<property name="openjpa.QueryCache" value="false"/>
Any idea?
Thanks
calling refresh() on an object inside trasaction does the trick :)

Categories

Resources