I'm inserting, updating and deleting many detached objects with hibernate and a c3p0 connectionpool. The problem is that hibernate does not batch the statements but instead does a
select @@session.tx_read_only
between every session.persist/insert/update/delete(object). Profiling the sql-connection it looks like this:
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
with select @@session.tx_rad_only always returning "0" (of course). It doesn't matter whether i use a stateless or stateful session. The resulting performance is not acceptable and far of any expectation.
My Hibernate Konfiguration:
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:4040/xy?zeroDateTimeBehavior=convertToNull</property>
<property name="hibernate.connection.username">xy</property>
<property name="hibernate.connection.password">xy</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">false</property>
<property name="hibernate.use_sql_comments">false</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">250</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.jdbc.batch_size">250</property>
<property name="hibernate.connection.release_mode">auto</property>
<property name="hibernate.order_inserts">true</property>
<property name="hibernate.order_updates">true</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="net.sf.ehcache.configurationResourceName">hibernate_ehcache.xml</property>
I'm using:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>ejb3-persistence</artifactId>
<version>1.0.2.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.4.Final</version>
</dependency>
I have nearly no expirience with hibernate and it is a good guess i made a huge mistake so please feel free to suggest anything. I switched to hibernate because the ORM functionality and am coming from plain jdbc prepared statements with a blazing fast performance. The MYSQL-Server is in a good configuration-state.
edit1: i'm aware of: Unnecessary queries in Hibernate - MySql I've got no transactional annotations in my entities nor a defined isolationlevel anywhere
edit2: i changed my connectionpool to bonecp - and the problem continues. Seems to be clearly a hibernate copnfiguration issue.
edit3: tried many different things and found maybe a trace of a hint: If I manualy session.flush() every 5 inserts (=size of batch e.g.)[tried the batch-example AGAIN from hibernate], the select @@session.tx_read_only query appears double - every 5 queries. I therefore assume that select @@session.tx_read_only is related to flushing. are there any ways to prevent hibernate from flushing every single insert/update? I tried so far: session.setFlushMode(FlushMode.COMMIT/NEVER/etc) without any change in the behaviour. Maybe I misconfigured anything... what does hibernate trigger to flush every insert? Unique constraint at the tables? hibernate validation framework? complex object-graphs? difficult concurrency? maybe a locking issue (Hibernate isn't sure if someone else locked the tables and doesn't batch but checks every single insert if the table is read only?)?
i found nothing related to this extrem (I assume) flushing bahaviour.
Making A Detached Object Persistent Again Hibernate allows detached objects to be associated with a persistence context again. One way to achieve this is to use the update method of the session. The update method forces an update operation to be fired for the passed object.
Hibernate monitors all persistent objects. At the end of a unit of work, it knows which objects have been modified. Then it calls update statement on all updated objects. This process of monitoring and updating only objects that have been changed is called automatic dirty checking in hibernate.
A detached entity is just an ordinary entity POJO whose identity value corresponds to a database row. The difference from a managed entity is that it's not tracked anymore by any persistence context. An entity can become detached when the Session used to load it was closed, or when we call Session.
You can again move a detached object to Persistent state by calling Session. update() or Session. saveOrUpdate() method.
We solved this issue by just setting useLocalSessionState=true in the connection string.
The below link explain the details of ReadOnly related changes happened from Mysql5.6 and the java connector 5.1.23. http://dev.mysql.com/doc/relnotes/connector-j/en/news-5-1-23.html
You need to include all those CRUD operations in a single Transaction so all statements are executed in the same DB connection.
You can also enable the following Hibernate configurations:
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<property name="hibernate.jdbc.batch_size" value="50"/>
Those queries don't mean you don't have batching. It's a MySQL thing
Some drivers require special batching reordering directives:
<property name="hibernate.connection.url">jdbc:mysql://host:port/db?rewriteBatchedStatements=true</property
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With