Search code examples
hibernatehibernate-criteria

How do I write a criteria to exclude some entities


I want to write a hibernate criteria that excludes certain entities. Here's what I have so far:

Criterion exclusion1 = Restrictions.not(Restrictions.conjunction()
    .add(Restrictions.eq("color", "blue");
    .add(Restrictions.eq("type", "aaa"))
    .add(Restrictions.eq("subtype1", "bbb"))
    .add(Restrictions.eq("subtype2", "ccc"));

Criteria crit = session.createCriteria(MyObject.class);
crit.add(exclusion1);

List result = crit.list();

There are several such exclusion criterion. This seems to do what I want except that if any of the fields are null I want it to be included. e.g an entity with color = blue, type = aaa, subtype1 and subtype2 are null to be included.

How can I rewrite this to not exclude that entity?


Solution

  • Here's something that works the way I want.

    From this answer, it seems that the proper way to do this is to use a subquery to define what should be excluded. e.g.

    Criterion exclusion1 = Restrictions.conjunction()
        .add(Restrictions.eq("color", "blue"))
        .add(Restrictions.eq("type", "aaa"))
        .add(Restrictions.eq("subtype1", "bbb"))
        .add(Restrictions.eq("subtype2", "ccc"));
    
    Criterion exclusion2 = Restrictions.conjunction()
        .add(Restrictions.eq("color", "blue"))
        .add(Restrictions.eq("type", "ddd"))
        .add(Restrictions.eq("subtype1", "eee"));
    
    DetachedCriteria excludes = DetachedCriteria.forClass(MyObject.class)
        .add(Restrictions.disjunction()
            .add(exclusion1)
            .add(exclusion2))
        .setProjection(Projections.property("id"));
    
    Criteria crit = session.createCriteria(MyObject.class);
    crit.add(Restrictions.eq("state","ok"));
    crit.add(Property.forName("id").notIn(excludes));
    
    List results = crit.list();
    

    I'm still interested in knowing if there's a better way, but this seems pretty good.