• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Hibernate generate select while storing object.

 
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 (?, ?, ?)
 
Ranch Hand
Posts: 84
Hibernate Eclipse IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Angel,

I did not get you properly, so can you please describe your solution in further details.
 
Angel Taveras
Ranch Hand
Posts: 84
Hibernate Eclipse IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 84
Hibernate Eclipse IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
reply
    Bookmark Topic Watch Topic
  • New Topic