0
votes

I have a two entity classes where i have hibernate many to one mapping. But when one of the class (QueryEntity) is fetched, the one to many collection Set lookUpCols (of class LookUpCols) is not getting loaded even though its fetch type is eager. I am getting queryEntity.getLookUpCols().size() = 0. In the back end, the HQL Query is generating as expected. Both the main entity and the eager entity query are being fired, but the object is not getting loaded.Can any one suggest why this is happening.

QueryEntity.java

package entity;
import java.util.Date;
import java.util.Set;

public class QueryEntity {
  Long queryId;
  ColumnMeta queryColumnMeta;
  QueryType queryType;
  String paramNames;
  String mainQuery;
  Date lastUpdtTS;
  public Set < LookUpCols > lookUpCols;
  String queryName;

  //getters and setters

}

QueryEntity.hbm.xml

<hibernate-mapping>
  <class name="entity.QueryEntity" table="QueryEntity">
    <meta attribute="class-description">
    </meta>
    <id name="queryId" type="long" column="queryId">
      <generator class="increment" />
    </id>
    <property name="paramNames" column="paramNames" type="string" />
    <property name="mainQuery" column="mainQuery" type="string" />
    <property name="queryName" column="queryName" type="string" />
    <many-to-one name="queryColumnMeta" column="queryColumnMeta" class="entity.ColumnMeta" />
    <set name="lookUpCols" table="LookUpCols" inverse="false" lazy="false" cascade="all" fetch="join">
      <key>
        <column name="queryId" />
      </key>
      <one-to-many class="entity.LookUpCols" />
    </set>
    <property name="queryType" column="queryType">
      <type name="org.hibernate.type.EnumType">
        <param name="enumClass">entity.QueryType</param>
        <param name="useNamed">true</param>
      </type>
    </property>
  </class>
</hibernate-mapping>

LookUpCols.java

package entity;
import java.util.Date;
public class LookUpCols {
Long lookUpId;
QueryEntity query;
String lookUpColName;
String lookUpQuery;
Date lastUpdtTS;

// getters and setters

}

LookUpCols.hbm.xml

<hibernate-mapping>
  <class name="entity.LookUpCols" table="LookUpCols">
    <meta attribute="class-description">
    </meta>
    <id name="lookUpId" type="long" column="lookUpId">
      <generator class="increment" />
    </id>
    <many-to-one name="query" column="query" class="entity.QueryEntity" fetch="select" not-null="true" />
    <property name="lookUpColName" column="lookUpColName" type="string" />
    <property name="lookUpQuery" column="lookUpQuery" type="string" />
    <property name="lastUpdtTS" column="lastUpdtTS" type="date" />
  </class>
</hibernate-mapping>

HQL QUeries

Hibernate:
  select
queryentit0_.queryId as queryId104_,
  queryentit0_.paramNames as paramNames104_,
  queryentit0_.mainQuery as mainQuery104_,
  queryentit0_.queryName as queryName104_,
  queryentit0_.queryColumnMeta as queryCol5_104_,
  queryentit0_.queryType as queryType104_
from
QueryEntity queryentit0_
Hibernate:
  select
lookupcols0_.queryId as queryId104_1_,
  lookupcols0_.lookUpId as lookUpId1_,
  lookupcols0_.lookUpId as lookUpId102_0_,
  lookupcols0_.query as query102_0_,
  lookupcols0_.lookUpColName as lookUpCo3_102_0_,
  lookupcols0_.lookUpQuery as lookUpQu4_102_0_,
  lookupcols0_.lastUpdtTS as lastUpdtTS102_0_
from
LookUpCols lookupcols0_
where
lookupcols0_.queryId = ?

Adding the code that runs fetches the Entity. This is the generic function that i call to read all data. I pass the class name (in this case QueryEntity) to this function which in turn fetches the data.

GenericDAOImpl.java

package daoImpl;
import java.io.File;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import dao.GenericDAO;
import exceptions.EntityNotPresent;

public class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {

SessionFactory factory;

public GenericDAOImpl() {
    super();
            Configuration cfg = new Configuration();
    File f = new File(
            "path to my persistence.xml");
    cfg.configure(f);
    factory = cfg.buildSessionFactory();

}

@Override
public T save(T t) {

    Session session = factory.openSession();
    session.beginTransaction().begin();
    session.persist(t);
    session.flush();
    session.beginTransaction().commit();
    session.close();
    return t;
}

//  This is the generic function that i call to read all data. I pass 
//  the class name (in this case QueryEntity) to this function which in turn    fetches the data. 
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public List<T> readAll(Class clazz) {
    Session session = factory.openSession();
    session.beginTransaction().begin();

    Query query = session.createQuery("from " + clazz.getName());
    List<T> listT = query.list();
    session.beginTransaction().commit();
    session.close();
    return listT;
}

@SuppressWarnings("unchecked")
@Override
public T readById(@SuppressWarnings("rawtypes") Class clazz, ID id) {
    /*
     * entityTransaction.begin(); T t = (T) entityManager.find(clazz, id);
     * entityTransaction.commit(); return t;
     */
    Session session = factory.openSession();
    session.beginTransaction().begin();
    T t = null;
    t = (T) session.load(clazz, id);
    session.beginTransaction().commit();
    session.close();
    return t;
}

@Override
public void delete(@SuppressWarnings("rawtypes") Class clazz, ID removeId) {

    if (isEntityExists(clazz, removeId)) {
        T old = readById(clazz, removeId);
        entityTransaction.begin();
        entityManager.remove(old);
        entityTransaction.commit();
    }
}

@SuppressWarnings("unchecked")
@Override
public boolean isEntityExists(@SuppressWarnings("rawtypes") Class clazz, ID id) {
    return entityManager.find(clazz, id) != null;
}

@SuppressWarnings("unchecked")
@Override
public T getFirstRecord(Class<?> clazz) {
    entityTransaction.begin();
    Session session = entityManager.unwrap(Session.class);
    Criteria queryCriteria = session.createCriteria(clazz);
    queryCriteria.setFirstResult(0);
    queryCriteria.setMaxResults(1);
    T t = (T) queryCriteria.list().get(0);
    entityTransaction.commit();
    return t;

}

@Override
public List<T> getByQuery(String queryExecute, Object[] pars, @SuppressWarnings("rawtypes") Class clazz) {

    entityTransaction.begin();
    @SuppressWarnings("unchecked")
    TypedQuery<T> query = entityManager.createQuery(queryExecute, clazz);
    for (int i = 0; i < pars.length; i++) {
        query.setParameter("arg" + i, pars[i]);
    }
    List<T> results = query.getResultList();
    entityTransaction.commit();
    return results;

}

@Override
public T update(@SuppressWarnings("rawtypes") Class clazz, ID id, T t) throws EntityNotPresent {
    return null;
}
}

So the query is correctly executing, but the collection is not getting loaded. Please help

1
Did you verify that you have the data that you are expecting the query to return? Also you are missing the code that runs the query.Bhesh Gurung
Hi Bhesh, Thanks for the reply. And yes, i have checkd the data. I am entering the data of the dependent table firs, seeing that it persists and then associate the persisted object with the QueryEntity object which also persists successfully. But while fetching, the collection containg the one to many relation is not being populated. I will still check it again and let you know. In the meantime, i have updated the DAO class where i fetch the data. I am using hibernate and Derby database.Gouravmoy Mohanty
Shouldnt this be the unique identifier of the table? <key> <column name="lookUpId" /> </key>terpinmd
Ahh.. Thanks @terpinmd.. Its correct. I am a bit new to hibernate. Don't know how I missed it. Thanks again. You can add this comment as an answer and I will mark it as answer.Gouravmoy Mohanty

1 Answers

0
votes

Per the comment in the OP the key was the incorrect column for the set. It should be:

<key> 
  <column name="lookUpId" /> 
</key> 

One thing that would help in the future is turning on the debugging that lets you see the values being bound in the queries. That would likely have shown you the wrong value was being passed for the "where lookupcols0_.queryId = ?" clause.