| 
					
						 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> 
					
  
						
					 |