1

So I keep coming up short on this, and just can't seem to get it to work right.

Things seem to work fine when I use my HibernateUtil.get(clazz, pkId) method, but when I try using the HibernateUtil.pagedQuery(clazz, criterion, start, stop) I get multiple identical objects returned.

For example if there were 3 employees assigned to Role 1, then running...

Role role = HibernateUtil.get(Role.class, new Integer(1));

... works as expected. However, if I run...

List<Criterion> c = new ArrayList();
c.add(Restrictions.eq("roleTypeSeqNo", new Integer(1)));
List<Role> roles = (List<Role>) phi.util.hibernate.HibernateUtil.pagedQuery(Role.class, c, 0, 50);

... returns a List of 3 identical roles. All of which represent Role 1.

If someone could guide me down the right path, I would really appreciate it.

Thanks in advance!

Here's an abbreviated version of my classes

@Entity
@Table(name="ASSIGNMENTS")
public class Assignment implements Serializable {
  @EmbeddedId
  private AssignmentPK pk;
  // After coming across many errors I finally caved and reverted roleTypeSeqNo back to just an Integer.
  private Integer roleTypeSeqNo;
  private String status;
  private String location;
}

@Embeddable
public class AssignmentPK implements Serializable {
  @ManyToOne
  @JoinColumn(name="EMPLID")
  private Employee employee;
  @Column(name="PRIORITY_NO")
  private String priorityNo;
}

@Entity
public class Employee implements Serializable {
  @Id
  private Integer emplId;
  private String name;
}

@Entity
public class Role implements Serializable {
  @Id
  private Integer roleTypeSeqNo;
  private Integer reportsToRole;
  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="roleTypeSeqNo")
  @JoinTable(
      name="ASSIGNMENTS"
      , joinColumns={@JoinColumn(name="ROLE_TYPE_SEQ_NO")}
      , inverseJoinColumns={
          @JoinColumn(name="EMPLID"),
          @JoinColumn(name="PRIORITY_NO")
      }
  )
  private List<Assignment> assignments;
}

public class HibernateUtil {
    public static Object get(Class clazz, Serializable pkId) {
        Session session = getSession();
        Transaction transaction = session.beginTransaction();

        Object obj = session.get(clazz, pkId);

        transaction.commit();
        session.close();

        return obj;
    }

    public static List pagedQuery(Class clazz, List<Criterion> criterion, Integer start, Integer size){
        Session session = getSession();
        try {
            Transaction transaction = session.beginTransaction();

            DetachedCriteria dCriteria = DetachedCriteria.forClass(clazz);
            for(Criterion c : criterion){
                dCriteria.add(c);
            }
            dCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
            dCriteria.setProjection(Projections.id());

            Criteria criteria=session.createCriteria(clazz);
            criteria.add(Subqueries.propertyIn("id", dCriteria));
            criteria.setFirstResult(start);
            criteria.setMaxResults(size);

            List records = criteria.list();

            transaction.commit();

            return records;
        } catch (Exception e) {
            Logger.getLogger("HibernateUtil").log(Level.SEVERE, "There was an EXCEPTION THROWN!!!", e);
            return null;
        } finally  {
            session.close();
        }
    }
}
2
  • can you please post your mapping file ? Commented Apr 26, 2012 at 4:51
  • I don't have a mapping file. I'm using annotations. Commented Apr 26, 2012 at 14:36

1 Answer 1

5
dCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

should be on the main criteria

criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

Also there is no need for the subquery there. The following is enough

    Criteria criteria = session.createCriteria(clazz);

    for(Criterion c : criterions){
        criteria.add(c);
    }

    criteria.setFirstResult(start);
    criteria.setMaxResults(size);

    List records = criteria.list();
Sign up to request clarification or add additional context in comments.

2 Comments

Can you please explain why is this needed? What is CriteriaSpecification.DISTINCT_ROOT_ENTITY doing ? In which situations do we get multiple results for the same object?
if you join a parent table and a child table (1-n) together the parent records are duplicated SELECT p.*, c.* FROM parenttable p JOIN childtable c ON p.Id = c.parent_id. Hibernate will emit a listelement per row returned but will use the same reference if the parentrecord is the same. DISTINCT_ROOT_ENTITY filters duplicate parent objects in the result so you get a list of distinct parent objects back.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.