Thursday, August 23, 2012

Exists via Criteria API

Parent class has List of Sons. (1:n)
        @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
        @Cascade( { CascadeType.SAVE_UPDATE, CascadeType.LOCK })
        @OrderBy("changeDate DESC")
Son has 1 Parent. (n:1)
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "parentoid", nullable = false)
FK is set on Son table to Parent and it is called PARENTOID.
How to get Parents that have at least 1 son?

select *
  from PARENT p
   where
       exists
            (select h.oid from SON h where p.oid = H.PARENTOID)

2 ways:
1) via Restrictions.isNotEmpty (easy)
DetachedCriteria crit= DetachedCriteria.forClass(Parent.class);
crit.add(Restrictions.isNotEmpty("sons"));

2) via Subqueries.exists - you can add more restrictions in subquery's WHERE clause
DetachedCriteria crit= DetachedCriteria.forClass(Parent.class);

DetachedCriteria subquery = DetachedCriteria.forClass(Son.class, "h");
subquery.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
subquery.setProjection(Projections.id());
subquery.add(Property.forName("parent").eqProperty(crit.getAlias() + ".oid"));
crit.add(Subqueries.exists(subquery));