views:

5189

answers:

3

Hi there. I have two tables related together using one-to-many relation : employee -> department : and relation through department_id in the employee table.

I use hibernate : and my hibernate mapping files are:

<?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"&gt;
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping default-lazy="false">
 <class catalog="moi"
  name="com.ebla.moi.correspondence.model.entity.user.User" table="user">
  <id name="id" type="java.lang.Long">
   <column name="id"/>
   <generator class="identity"/>
  </id>
  <many-to-one
   class="com.ebla.moi.correspondence.model.entity.department.Department"
   fetch="select" name="department">
   <column name="department_id"/>
  </many-to-one>
  <property generated="never" lazy="false" name="name" type="java.lang.String">
   <column length="128" name="name" not-null="true"/>
  </property>
  <property generated="never" lazy="false" name="email" type="java.lang.String">
   <column length="128" name="email" not-null="true" unique="true"/>
  </property>
  <property generated="never" lazy="false" name="maritalStatus" type="java.lang.Short">
   <column name="marital_status" not-null="true"/>
  </property>
  <property generated="never" lazy="false" name="hireDate" type="java.lang.String">
   <column length="64" name="hire_date"/>
  </property>
 </class>
</hibernate-mapping>

and the second mapping file is :

<?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"&gt;
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping default-lazy="false">
 <class catalog="moi"
  name="com.ebla.moi.correspondence.model.entity.department.Department" table="department">
  <id name="id" type="java.lang.Long">
   <column name="id"/>
   <generator class="identity"/>
  </id>
  <property generated="never" lazy="false" name="name" type="java.lang.String">
   <column length="256" name="name" unique="true"/>
  </property>
  <set inverse="true" name="users" sort="unsorted">
   <key>
    <column name="department_id"/>
   </key>
   <one-to-many class="com.ebla.moi.correspondence.model.entity.user.User"/>
  </set>
 </class>
</hibernate-mapping>

My problem is : sometimes i need to get the employee with his department, and other times i need only the employee information with out department information..... and the same thing with department with employee.... using the mapping file above the hibernate bring the department and it's users if i need the employee or not... how to define my needs to hibernate to fetch just what i need...

thank you

+3  A: 

You could map the relation as "lazy" and write two queries to get your datas:

  • The usual simple query to get your data ("lazy"). E.g. "select e from Employee e where ..."

  • The same query using "fetch join" to force Hibernate to fetch "childs". E.g. "select e from Employee left join fetch e.department where ..."

LLP, Andrea

andcoz
+1  A: 

You can use ICriteria to fetch your Employee.

You can use the SetFetchMode method of the ICriteria to determine whether the Department should be fetched, or not:

This will make sure that the Department is not fetched:

ICriteria crit = theSession.CreateCriteria (typeof(Employee));
crit.SetFetchMode ("Department", FetchMode.Lazy)

With this code, the department will be fetched.

ICriteria crit = theSession.CreateCriteria (typeof(Employee));
crit.SetFetchMode ("Department", FetchMode.Join)

Some say that it is best-practice to use the default fetchmode in the mappings (which would be lazy, i guess), and specify the fetch-mode in every specific scenario. (That is, in your repositories).

Frederik Gheysels
A: 

One way of doing this is to have two classes representing an employee:

  • Employee which has department information mapped through;
  • EmployeeSummary which only has the employee data itself.

Both classes then have independent bindings onto the employee table, but only Employee also has the relationship onto department defined.

Then when you need all the information you load Employee instances, and when you just need employee information you load EmployeeSummary instances.

You can remove any duplication of ORM bindings and business logic by introducing a common superclass like AbstractEmployee to both of the employee classes.

Dan Vinton
I don't think this is a good idea in this situation. What if your classes contain complex BL ? You'll have to duplicate it ?
Frederik Gheysels
Not necessarily if you introduce the common superclass, but good point - I've updated the answer to reflect this.
Dan Vinton
What if in a single session both an Employee and an EmployeeSummary where loaded from the same database record, then one or both of them were changed?
Ian Ringrose
This can happen anyway - what if two instances of the employee record were independently loaded and changed? Hopefully your Hibernate version number field would save you either way...
Dan Vinton

related questions