Why is NHibernate's adonet.batch_size setting ignored - session.SetBachSize() throws exception? - nhibernate

I am using NHibernate and switched from my local SQLExpress database to Oracle11g.
My code started to complain. The session objects method SetBatchSize() throws a System.NotSupported exception:
No batch size was defined for the session factory, batching is disabled. Set adonet.batch_size = 1 to enable batching.
It worked on the SQLExpress database. Ok, so I added this
<property name="adonet.batch_size">1</property>
to the config but it still throws the same exception. The sessions Batcher property is set to this
Value: {NHibernate.AdoNet.NonBatchingBatcher}
Type: NHibernate.Engine.IBatcher {NHibernate.AdoNet.NonBatchingBatcher}
It does not make any difference if i try to set the batch size in- or outside the transaction.

NHibernate has only batcher for some RDBMs. if it doesn't find one for the database in question it defaults to nonbatchingbatcher which is not able to batch at all. you could implement your own IBatcher.

Related

How to log in hibernate which part of the code caused a given SQL

We can turn on all of the SQL related logging with the following settings in spring:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type=trace
If we have a standalone hibernate/springdata command like
myEntityRepository.save(myEntity);
OR
enityManager.persist(myEntity);
then it is easy to debug what happened just by reading the generated SQL from the log.
But, how would you debug when there isn't any explicit ORM action like here:
#Transactional
void doHundredOfTask(Long id){
MyEntity myEntity = myEntityRepository.findById(id);
// here comes ton of action on the entity like settings field,setting/adding to collection
// myEntity.setField1()..
//myEntity.setField2()
// ....
// myEntity.setField_N()
// myEntity.getSomeList.get(0).setSomeField()
// no ORM action
}
At the end we don't explicitly save anything but after the transaction hibernate will flush the changes, hence a massive amount of SQL will occur in the log. If you have a ton of action on the entity and on it's associations then it is extremly hard to debug why a given SQL was triggered.
Is there a way to assign the generated SQL to the triggering code in the log?
edit: Right know all I can do is splitting up the code to smaller chunks / or commenting out some part of it. But this process is slow..
p6spy can print a stacktrace for each executed SQL statement. Here is configuration to enable this: stacktrace=true.
How to configure p6spy for maven project:
Add p6spy dependency
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
Wrap the jdbc connection with p6spy:
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/xxx
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
Add spy.properties config src/main/resources/spy.properties
stacktrace=true
appender=com.p6spy.engine.spy.appender.Slf4JLogger
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
You can remove the properties bellow:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
With this configuration, p6spy will output SQL and the stacktrace. E.g.:
select x0_.id as id1_7_ from X x0_
15:10:16.166 default [main] INFO c.p.e.spy.appender.Slf4JLogger[logException]-39 -
java.lang.Exception: null
at com.p6spy.engine.common.P6LogQuery.doLog(P6LogQuery.java:126)
...
at org.hibernate.loader.Loader.getResultSet(Loader.java:2341)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2094)
...
at com.springapp.Test.test(Test.java:36)
...

How to disable all operations on ignite cache when topology is not valid

I have 2 server nodes and one client node. I am using TopologyValidator to validate the topology.
If any server node left the cluster I want disable all operations. TopologyValidator disables only update operation not get operation. Can you help me to do this?
Currently TopologyValidator disables update operations only.
You can use IgniteCache#close() operations to disable all operations on specific caches.
See: https://ignite.apache.org/releases/latest/javadoc/org/apache/ignite/IgniteCache.html#close--
If you do the following:
IgniteCache cache = ignite.getOrCreateCache(config);
cache.put(1L , new Person(1L, "A", "B"));
cache.close();
System.out.println(cache.get(1L)); //exception here.
you will get the following exception on the get call:
[INFO ][exchange-worker-#43%node1%][GridCacheProcessor] Finish proxy initialization, cacheName=test1, localNodeId=...
Exception in thread "main" java.lang.IllegalStateException: Cache has been closed: test1
at org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.checkProxyIsValid(GatewayProtectedCacheProxy.java:1548)
at org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.onEnter(GatewayProtectedCacheProxy.java:1580)
at org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.get(GatewayProtectedCacheProxy.java:634)
In addition to Alex's answer, you might implement a custom analog of the TopologyValidator. All you need is to listen for the EVT_NODE_LEFT and EVT_NODE_JOINED events to trigger the custom logic, like stopping a cache or switching some application access validator.

change jta transaction timeout from default to custom

I am using Atomikos for JTA transaction.
I have following setting for JTA:
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(900);
but when my code perform JTA transaction, then if it takes more than 5 minutes (which is default value) then it throws exception:
Caused by: com.atomikos.icatch.RollbackException: Prepare: NO vote
at com.atomikos.icatch.imp.ActiveStateHandler.prepare(ActiveStateHandler.java:231)
at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:681)
at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:970)
at com.atomikos.icatch.imp.CompositeTerminatorImp.commit(CompositeTerminatorImp.java:82)
at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:336)
at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:190)
... 25 common frames omitted
it looks like its taking the default jta transaction timeout (even though i am setting timeout explicitely (to 15 minutes/900 seconds).
I tried using following properties in application.properties file however it still takes the default timeout value(300 seconds).
spring.jta.atomikos.properties.max-timeout=600000
spring.jta.atomikos.properties.default-jta-timeout=10000
I have also tried with below property but no luck:
spring.transaction.default-timeout=900
Can anyone suggest if I need any other setting? I am using wildfly plugin, spring boot and atomikos api for JTA transaction.
From the Atomikos documentation:
com.atomikos.icatch.max_timeout
Specifies the maximum timeout (in milliseconds) that can be allowed for transactions. Defaults to 300000. This means that calls to UserTransaction.setTransactionTimeout() with a value higher than configured here will be max'ed to this value. For 4.x or higher, a value of 0 means no maximum (i.e., unlimited timeouts are allowed).
Indeed, if you take a look at the Atomikos library source code (for both versions 4.0.0M4 and 3.7.0), in the createCC method from class com.atomikos.icatch.imp.TransactionServiceImp you will see:
387: if ( timeout > maxTimeout_ ) {
388: timeout = maxTimeout_;
389: //FIXED 20188
390: LOGGER.logWarning ( "Attempt to create a transaction with a timeout that exceeds maximum - truncating to: " + maxTimeout_ );
391: }
So any attempt to specify a longer transaction timeout gets capped to maxTimeout_ which has a default value of 300000 set during initialization if none is specified.
You can set the com.atomikos.icatch.max_timeout as a JVM argument with:
-Dcom.atomikos.icatch.max_timeout=900000
or you could use The Advanced Case recipe specified in the Configuration for Spring Section from the Atomikos documentation.
I've resolved similar problem where configuration in application.yml (or application. properties) of Spring Boot did not get picked up.
There was even a log that I later found mentioned in official docs.
However, I added transactions.properties file (next to the application.yml) where I set mine desired properties.
# Atomikos properties
# Service must be defined!
com.atomikos.icatch.service = com.atomikos.icatch.standalone.UserTransactionServiceFactory
# Override default properties.
com.atomikos.icatch.log_base_dir = ./atomikos
Some properties can be set within transactions.properties and other within jta.properties file.

Releasing XASession XAResource - Manual enlisting

In our MDB we have a Xatransaction between DB and Tibco foreign server Queue. we have enlisted the foreign server XaResouce using below.
The MDB is on Weblogic server 10.3.6, JDK 1.6.
init()---
XAConnection tempXAConn = xaConn;
TibjmsXAConnectionFactory xaConnFactory = (TibjmsXAConnectionFactory)ServiceLocator.getInstance().getJNDIReferencedObject(JMS_Q_CONNECTION_FACTORY_JNDI_XA);
xaConn = xaConnFactory.createXAConnection(JMS_USER,JMS_PSWD);
getsession()---
XASession xaSession = xaConn.createXASession();
TransactionHelper txHelper = TransactionHelper.popTransactionHelper();
Transaction tx = txHelper.getTransaction();
tx.enlistResource(xaSession.getXAResource());
Transactions are working fine. we are using one connection and create new xasession for every message.
but the problem is releasing resources. after few thousand msgs i see heap containing same number of Tibjmsxasession,Tibjmsxaresource,Tibjmslongkey objects. this leads to outofmemory issue.
we cannot use session.close() in between the transaction.
The transaction are container managed. only enlisting is done manually.
i used
tx.registerSynchronization(new SessionSynchronization());
SessionSynchronization implements Synchronization and has 2 methods afterCompletion and beforeCompletion.
session.close can be called inside afterCompletion. session can be maintained in threadlocal.

Timeout exception when timeout set to infinite time

In my C# .NET 3.5 application I am using CastleProject ActiveRecord over NHibernate. This is desktop application using MS SQL Server 2008. I have set ADO command timeout to 0 to prevent timeout exception during bulk operations:
<activerecord>
<config>
...
<add key="hibernate.command_timeout" value="0" />
</config>
</activerecord>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
...
<property name="command_timeout">0</property>
</session-factory>
</hibernate-configuration>
However, I am still receiving timeout exception! The NHibernate log shows something like this:
Somewhere at the beginning:
2010-10-02 06:29:47,746 INFO
NHibernate.Driver.DriverBase - setting ADO.NET command timeout to 0 seconds
Somewhere at the end:
2010-10-02 07:36:03,020 DEBUG
NHibernate.AdoNet.AbstractBatcher -
Closed IDbCommand, open IDbCommand s:
0 2010-10-02 07:36:03,382 ERROR
NHibernate.Event.Default.AbstractFlushingEventListener
- Could not syn chronize database state with session
NHibernate.HibernateException: An
exception occurred when executing
batch queries ---> System.Data.S
qlClient.SqlException: Timeout
expired. The timeout period elapsed
prior to completion of the opera tion
or the server is not responding. at
System.Data.SqlClient.SqlConnection.OnError(SqlException
exception, Boolean breakConnection)
How come? How to fix this?
It's correct that a value of 0 indicates no timeout (as defined in the MSDN docs), however while NHibernate's driver passes the config value to the db command when it's >= 0, the batcher's condition checks that the value is > 0.
Therefore, when you set batching on, with a timeout value of 0, the value isn't carried over to the db command so it remains as default.
It's entirely possible that this is by design, and that NHibernate developers intentionally disabled disabling timeouts for batch scenarios. Disabling timeout is a bad idea anyway, if you have troubles with timeout errors I would raise the value, but not disable it.
Please confirm this with NHibernate devs.
You might be looking to set the timeout for specific queries and not at web.config level (otherwise you really need to tune up your application :) ).
I've recently found this answer that helped me:
How to set Nhibernate LINQ Command Timeout using Session.Query