-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: JOIN fetch mode works but SELECT does not
PostPosted: Tue Nov 07, 2006 3:29 pm 
Newbie

Joined: Fri Oct 14, 2005 8:37 am
Posts: 10
Location: University of Edinburgh
Hello,

I am having performance problems with persisting a collection of
classes due (it seems to me) to the use of FetchMode.JOIN. I have
tried with FetchMode.SELECT but I have not managed to make it work, so
I am sending this email hoping to get some good hints towards a
solution to my problems.

I need to persist and consult instances of the class
LearnerModel. Each LearnerModel has a Map of Beliefs, with
BeliefDescriptors as keys. Each Belief contains a MassDistribution and
a List of Evidence, and each Evidence contains a MassDistribution and
other small fields.

I use an accessory class, called XlmSession to hide the details of the
persistence mechanism. When an XlmSession is open, with a given
learner identifier, then it retrieves the corresponding learner model
from the database, using FetchMode.JOIN. Then it produces individual
beliefs on request. The problem is that LearnerModels become quite big
and then FetchMode.JOIN becomes highly inefficient (even with second
level cache enabled). But if I try to use FetchMode.select, then only a
small fraction of the Map of Belief is retrieved.

See code extracts and mappings below for details. Please feel free to
send me any hints!

Hibernate version: 3.0.5
Database name and version: 10.0.2.1

Regards,

Rafael

package org.activemath.xlm.model;

public class XlmSession {

private int mode;
private LearnerModel lModel;
private String learnerId;
private Session session;
private Transaction transaction;

public static XlmSession getSession( String learnerId, int mode) {
XlmSession s = null;
try {
s = new XlmSession( learnerId, mode);
}
catch (XlmException e) {
return null;
}

return s;
}

public void release()
{
if (session == null) {
log.warn( "No Hibernate session to close.");
}
else {
if (transaction == null)
log.warn( "No transaction to release!");
else {
try {
transaction.commit();
}
catch (HibernateException e) {
log.error( "..." , e);
transaction.rollback();
}
finally {
session.close();
transaction = null;
session = null;
}
}
}
}

private XlmSession( String learnerId, int mode)
throws XlmException
{
this.learnerId = learnerId;
this.mode = mode;
session = HibernateHelper.getInstance().getXlmModelSession();

if (session == null) {
throw new XlmException( "...");
}

transaction = null;
XlmException exception = null;
try {
transaction = session.beginTransaction();
Criteria criteria = session.createCriteria( LearnerModel.class)
// The following line is the one that produces a full
// load of the learner model. It is included here
// because I have not been able so far to make
// select/lazy fetching to work. Use of Hibernate
// second-level cache makes this line a bit less harmful.
.setFetchMode( "beliefs", FetchMode.JOIN)
// This is the line that does not work.
// .setFetchMode( "beliefs", FetchMode.SELECT)
.add( Restrictions.eq( "learnerId", learnerId));

lModel = (LearnerModel) criteria.uniqueResult();
if (lModel == null)
throw new XlmException( "...");
}
catch (Exception e) {
if (transaction != null)
transaction.rollback();
exception = new XlmException( e.getMessage());
}
finally {
if (exception != null) {
session.close();
throw exception;
}
}
}

public LearnerModel getModel() {
// TODO Auto-generated method stub
return lModel;
}

public Belief getBelief( BeliefDescriptor descriptor) {
return lModel.getBelief( descriptor);
}

public synchronized BeliefDescriptor persistBeliefDescriptor(
BeliefDescriptor desc)
{
NaturalIdentifier natId = descriptorAsIdentifier( desc);
Criteria criteria = session.createCriteria( BeliefDescriptor.class);
criteria.add( natId);

BeliefDescriptor pDesc = null;
Transaction t = null;
try {
t = session.beginTransaction();
pDesc = (BeliefDescriptor) criteria.uniqueResult();
t.commit();
}
catch (HibernateException e) {
if (t != null)
t.rollback();
return null;
}

if (pDesc != null) {
return pDesc;
}
else {
t = null;
try {
t = session.beginTransaction();
session.save( desc);
t.commit();
}
catch (HibernateException e) {
if (t != null)
t.rollback();
desc = null;
}
return desc;
}
}

private static NaturalIdentifier descriptorAsIdentifier(
BeliefDescriptor desc)
{
NaturalIdentifier id = new NaturalIdentifier().set( "metacogId",
desc.metacogId).set( "affectId", desc.affectId).set(
"motivationId", desc.motivationId).set( "competencyId",
desc.competencyId).set( "capeId", desc.capeId).set( "domainId",
desc.domainId);

return id;
}
...
}


CLASSES
======================================================================

package org.activemath.xlm.model;
...

public class LearnerModel {
private long id;
Map beliefs;

LearnerModel() {
learnerId = null;
beliefs = null;
}

LearnerModel(String learnerId) {
this.learnerId = learnerId;
this.beliefs = new Hashtable();
}

String getLearnerId() {
return learnerId;
}

public long getId() {
return id;
}

void setLearnerId(String learnerId) {
this.learnerId = learnerId;
}

public Belief getBelief(BeliefDescriptor beliefId) {
Belief b = (Belief) beliefs.get(beliefId);

return (b != null) ? b : new Belief();
}
...
}

======================================================================

package org.activemath.xlm.model;

public class Belief {
LearnerModel lModel;
BeliefDescriptor descriptor;

private List evidence;
MassDistribution massDist;

public Belief() {
this.massDist = new MassDistribution();
this.evidence = new ArrayList();
}

public Belief(LearnerModel model, BeliefDescriptor desc) {
this();
this.lModel = model;
this.descriptor = desc;
}
...
}

======================================================================

package org.activemath.xlm.model;

public class MassDistribution {

private double[] massDist;
...
}

======================================================================

package org.activemath.xlm.model;

public class Evidence {
private long eventId;
private int type;
private int action;
private double discount;
private MassDistribution mass;

...
protected Evidence()
{
eventId = -1;
type = DIRECT;
action = ADD;
discount = DEFAULT_DISCOUNT;
mass = new MassDistribution();
}
...
}

======================================================================

package org.activemath.xlm.model;

public class BeliefDescriptor {

String metacogId;
String motivationId;
String affectId;
String competencyId;
String capeId;
String domainId;

protected static final String UNSET = "_UNSET";
protected static final String PRINTABLE_UNSET = "_";

private long id;

public BeliefDescriptor ()
{
metacogId = UNSET;
affectId = UNSET;
motivationId = UNSET;
competencyId = UNSET;
capeId = UNSET;
domainId = UNSET;
}

/**
* Produces a deep copy of the given belief descriptor.
*
* @return An instance that is a deep copy of the given instance.
*/
public BeliefDescriptor (BeliefDescriptor model)
{
metacogId = model.metacogId;
affectId = model.affectId;
motivationId = model.motivationId;
competencyId = model.competencyId;
capeId = model.capeId;
domainId = model.domainId;
}
...
}


MAPPINGS
======================================================================

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"conf/hibernate/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.activemath.xlm.model">
<class name="LearnerModel" table="LModel">
<cache usage="read-write"/>
<id name="id" access="field" type="long">
<generator class="native" />
</id>

<natural-id>
<property name="learnerId" access="field"/>
</natural-id>

<map name="beliefs" inverse="true" cascade="all-delete-orphan">
<cache usage="read-write"/>
<key column="lModelId" on-delete="cascade"/>
<map-key-many-to-many class="BeliefDescriptor"
column="descriptorId" />
<one-to-many class="Belief"/>
</map>
</class>
</hibernate-mapping>


======================================================================

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"conf/hibernate/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping default-access="field"
package="org.activemath.xlm.model">
<class name="Belief" table="Belief" >
<cache usage="read-write" />
<id type="long">
<generator class="native" />
</id>

<natural-id>
<many-to-one name="lModel" access="field" class="LearnerModel"
column="lModelId" not-null="true"/>
<many-to-one name="descriptor" access="field"
class="BeliefDescriptor" column="descriptorId" not-null="true"/>
</natural-id>

<property name="unresolved" />

<component class="MassDistribution" name="massDist">
<primitive-array name="massDist" table="MassDist">
<key column="Belief_id"/>
<list-index column="lSetOrd"/>
<element column="bpa" type="double" />
</primitive-array>
</component>
<list access="field" name="evidence" cascade="all,delete-orphan">
<cache usage="read-write"/>
<key column="Belief_id" not-null="true"/>
<list-index column="n" />
<one-to-many class="Evidence"/>
</list>
</class>
</hibernate-mapping>


======================================================================

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"conf/hibernate/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.activemath.xlm.model">
<class name="Evidence" table="Evidence">
<cache usage="read-write" />
<id type="long">
<generator class="native"/>
</id>
<property name="eventId"/>
<property name="type"/>
<property name="action"/>
<property name="discount"/>
<component class="MassDistribution" name="mass">
<primitive-array name="massDist" access="field" table="EventInterp">
<key not-null="true" column="Evidence_id"/>
<list-index column="lSetOrd"/>
<element column="bpa" type="double"/>
</primitive-array>
</component>
</class>
</hibernate-mapping>


======================================================================

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"conf/hibernate/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="org.activemath.xlm.model.BeliefDescriptor" lazy="false"
table="BDesc">
<cache usage="read-write" />
<id name="id" access="field" type="long">
<generator class="native" />
</id>

<natural-id>
<property name="metacogId" access="field">
<column name="metacogId" sql-type="varchar(80)"/>
</property>
<property name="motivationId" access="field">
<column name="motivationId" sql-type="varchar(80)"/>
</property>
<property name="affectId" access="field">
<column name="affectId" sql-type="varchar(80)"/>
</property>
<property name="competencyId" access="field">
<column name="competencyId" sql-type="varchar(80)"/>
</property>
<property name="capeId" access="field">
<column name="capeId" sql-type="varchar(80)"/>
</property>
<property name="domainId" access="field">
<column name="domainId" sql-type="varchar(80)"/>
</property>
</natural-id>
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 07, 2006 3:42 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Did you verify that your second level cash is actually used? You can check this if you enable SQL output in your hibernate configuration and see that the requests decrease when repeatingly hitting the same data.

FetchMODE.SELECT should work. If you get a Lazy Intializing Exception you should call

Hibernate.initialize(objekt.childObjects);
this will hit the cache.

Have a look at the Hibernate Reference as well.
16.9. Queries by natural identifier

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 07, 2006 4:28 pm 
Newbie

Joined: Fri Oct 14, 2005 8:37 am
Posts: 10
Location: University of Edinburgh
Thank you for your reply. Actually, I get no exceptions, just incomplete collection of beliefs in SELECT fetch mode. Tried with a Criteria query for the belief:

public Belief getBelief( BeliefDescriptor descriptor)
{
NaturalIdentifier natId = descriptorAsIdentifier( descriptor);

BeliefDescriptor pescriptor = null;
Belief belief = null;
Transaction t = null;

try {
Criteria criteria =
session.createCriteria( BeliefDescriptor.class)
.add( natId);
t = session.beginTransaction();
pescriptor = (BeliefDescriptor) criteria.uniqueResult();

if (pescriptor != null) {
criteria = session.createCriteria( Belief.class)
.add( Restrictions
.and(Restrictions.eq( "lModel", lModel),
Restrictions.eq( "descriptor", pescriptor)));
belief = (Belief) criteria.uniqueResult();
}
t.commit();
}
...
}

but it also seems to depend on using JOIN fetch mode. I will test the second level cache as you suggested, and revise the documentation for Hibernate.initialize.

Regards,

Rafael


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.