0

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?

Mikko Maunu
  • 41,366
  • 10
  • 132
  • 135
  • An entity with a null subtype1 is not matched by the restriction `eq("subtype1", "bbb")`, so it's also not mapped by the conjunction, so it's included. You don't need to change anything to your code. – JB Nizet Jul 01 '15 at 11:19
  • Yeah, that's what I thought. However it's still not doing what I want. I hope someone can figure out the proper way to do what I want. – Alex J. Roberts Jul 02 '15 at 00:49

1 Answers1

1

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.

Community
  • 1
  • 1