wood burning stoves 2.0*
The moose likes Object Relational Mapping and the fly likes Hibernate generate select while storing object. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Hibernate generate select while storing object." Watch "Hibernate generate select while storing object." New topic
Author

Hibernate generate select while storing object.

Ashok Mor
Ranch Hand

Joined: Jul 17, 2007
Posts: 44
Hi,
Here we are using JTA transaction and Ehcache, first we are taking TransactionManager instance to manage the transaction across
different sessions, then we have single instance of SessionFactory instance through which we are taking instances of Session Object,
here we are taking Different Session object to store each object , and after storing each object we flush and close the session.
First we store all dependent object first and then store other object, but what hibernate does is that , when we go for storing other object it applies the
select query for dependent object even though they stored before
, so it cause the performance problem, so if any one can help us in overcome this
issue? for example below i have mentioned my sample code and configuration part.


I.E.
-> here we are initiating common SessionFactory instance
public static final SessionFactory sessionFactory;
static {
try{
// Create the SessionFactory
Configuration configuration = new Configuration();
//configuration.setInterceptor(new AsiteInterceptor());
sessionFactory = configuration.configure().buildSessionFactory();
}catch(Throwable ex){
// Make sure you log the exception, as it might be swallowed
throw new ExceptionInInitializerError(ex);
}
}

-> initiating Transaction manager and being the transaction.

InitialContext ctx = new InitialContext();
TransactionManager tm = (TransactionManager)ctx.lookup("java:/TransactionManager");
tm.begin();
Transaction ts = tm.getTransaction();

-> Opem new Session object from SessionFactory and stroing instance of ClassC, and closing the session after storing.
session = HibernateUtil.getSessionFactory().openSession();
session.save(objc);
session.flush();
session.close();

-> creating another Session object from same SessionFactory and stroing instance of ClassB which has references of above object

session = HibernateUtil.getSessionFactory().openSession();
//session.setCacheMode(CacheMode.NORMAL); //does not effect the outcome.
session.save(objb);
ession.flush();
session.close();

so what the problem us while storing this object in DB it applies select for it referenc object of ClassC

-> now how we configure Ehcache in our application
hibernate.hb.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>

<!-- <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
<property name="connection.url">jdbc:jtds:sqlserver://dbbox:1433;DatabaseName=AsiteModelServer</property>
<property name="connection.username">dmsdb</property>
<property name="connection.password">dmsdb</property>
-->

<property name="connection.pool_size">10</property>
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>

<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>

<property name="hibernate.connection.datasource">java:AmsDS</property>
<property name="current_session_context_class">jta</property>
<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
<property name="jta.UserTransaction">java:comp/UserTransaction</property>

<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.use_minimal_puts">true</property>
<property name="hibernate.generate_statistics">true</property>
<property name="hibernate.cache.use_structured_entries">true</property>


<mapping resource="mapping/classb.hbm.xml"/>

</session-factory>
</hibernate-configuration>

--mapping file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping>

<class name="com.test.ClassB" table="ClassB">
<cache usage="read-only"/>
<id name="id">
<generator class="assigned"/>
</id>
<property name="bdata"/>
<many-to-one name="classc" class="com.test.ClassC" />
</class>

<class name="com.test.ClassC" table="ClassC">
<cache usage="read-only"/>
<id name="id">
<generator class="assigned"/>
</id>
</class>
</hibernate-mapping>

ehcache.xml

<ehcache>
<cache name="com.test.ClassB"
maxElementsInMemory="450"
eternal="false"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="com.test.ClassC"
maxElementsInMemory="450"
eternal="false"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>

SQL log for this storing

20:24:37,109 INFO [STDOUT] Hibernate: insert into ClassC (id) values (?)
20:24:37,140 INFO [STDOUT] Hibernate: select classc_.id from ClassC classc_ where classc_.id=?
20:24:37,140 INFO [STDOUT] Hibernate: insert into ClassB (bdata, classc, id) values (?, ?, ?)
Angel Taveras
Ranch Hand

Joined: Nov 13, 2008
Posts: 84

Hello Ashok, a had an application that had the same behavior as your and all i did to solve it, was to add a version column to each of the entities. I think that it's that without it hibernate doesn't have a reliable mechanism to know if the entity it's transient or not and because of it, hibernate have to perform a select query before save/update the entity.

regards,
Ashok Mor
Ranch Hand

Joined: Jul 17, 2007
Posts: 44
Hi Angel,

I did not get you properly, so can you please describe your solution in further details.
Angel Taveras
Ranch Hand

Joined: Nov 13, 2008
Posts: 84

Hibernate use a mechanism to determine if the entity that's gonna be persisted it's transient or not. One of them mechanism it's using versioning,



With this you'll avoid the select before insert but also a locking mechanism and concurrency control.
Ashok Mor
Ranch Hand

Joined: Jul 17, 2007
Posts: 44
Hi,

But that can also be done through overriding Interceptor i.e.


Configuration configuration = new Configuration();
configuration.setInterceptor(new UserInterceptor());
sessionFactory = configuration.configure().buildSessionFactory();

public class UserInterceptor extends EmptyInterceptor{

public Boolean isTransient(Object object) {
return Boolean.TRUE;
}
}

So here we have override the method called isTransient(), which return true, that means this object is transient no need to save.

In this case it also does not generate select, but again it leads to another problem that, it does not store reference for referencing of object being save.

Like
A has reference of C,
First we store C,
Then we store A, but while storing A it does not save reference of C into table of A, instead of that it saved that as a null value.
This happens in case of JTA transaction only.
Angel Taveras
Ranch Hand

Joined: Nov 13, 2008
Posts: 84

Yes, but the interceptor it's used for a different purpose and certainly that Hibernate need to know when a entity it's transient or not because if it's never transient then it will try to perform an update to a row that doesn't exist, instead on performing an insert. This could be desired if you insert your data from an external system and that only you want to make selects an updates with hibernate
 
Don't get me started about those stupid light bulbs.
 
subject: Hibernate generate select while storing object.
 
Similar Threads
NullPointerException on SessionFactory sessionFactory = new Configuration().configure().buildSession
Dialect class not found
Not able to find the added record in table.
Cannot insert record into Database!
NullPointerException in session.flush()