Создание динамического запроса критериев гибернации с подкритериями - PullRequest
1 голос
/ 23 сентября 2011

У меня есть класс Java, поле которого помечено @SearchCriteria(criteria = "class1.class2.field"). criteria параметр внутри аннотации означает, что для класса это поле должно быть установлено в качестве критерия гибернации, это означает, что если поле помечено, например:

@SearchCriteria(criteria = "class1.class2.field")
private String value;

Я хочу динамически создавать критерии гибернации с помощью вида

.
DetachedCriteria hibernateCriteria = forClass(Class.class);
hibernateCriteria.createCriteria("class1").createCriteria("class2").add(eq("field", value));

Проблема в том, что я не могу установить другой критерий для уже добавленного, это означает, что я должен проверить аннотацию criteria опция.

      switch (annotationCriteria.length - 1) {
case 0:             
hibernateCriteria.add(isNull(annotationCriteria[0]));               
case 1:
hibernateCriteria.createCriteria(annotationCriteria[0]).add(                Restrictions.isNull(annotationCriteria[annotationCriteria.length - 1]));
case 2:   hibernateCriteria.createCriteria(annotationCriteria[0]).createCriteria(annotationCriteria[1]).add(                Restrictions.isNull(annotationCriteria[annotationCriteria.length - 1]));
    }

Я хочу удалить этого "свита". Можно получить уже добавленные критерии, я не делаю сейчас, например, по «имени», и это добавляет новые подкритерии для него.

Ответы [ 2 ]

1 голос
/ 20 января 2012

Я нашел более "хорошее" решение для этой проблемы. Прежде всего создайте некоторый класс searchCriteria, например:

public class SearchCriteria {

    @SearchCriteria(path = "someclass.someclass.id")
    private Integer someId;

    public Integer getSomeId() {
        return someId;
    }

    public void setSomeId(Integer someId) {
        this.someId= someId;
    }
}

И пользовательская аннотация:

@Target(value = { ElementType.FIELD })
@Retention(RUNTIME)
public @interface SearchCriteria {
    String path() default "";

    boolean optional() default true;
}

А в классе DAO:

@Override
    public Collection<SomeClass> find(SearchCriteria criteria) {
        DetachedCriteria hibernateCriteria = forClass(SomeClass.class);

        for (Field field : criteria.getClass().getDeclaredFields()) {
            Annotation annotation = field.getAnnotation(SearchCriteria.class);

            if (annotation == null) {
                continue;
            }

            List<String> elements = Arrays.asList(StringUtils.split(((SearchCriteria) annotation).path(), "."));

            field.setAccessible(true);
            Object fieldValue = null;
            try {
                fieldValue = field.get(criteria);
            } catch (IllegalArgumentException e) {
                LOG.error("while trying to get private field value of entity " + SearchCriteria.class, e);
            } catch (IllegalAccessException e) {
                LOG.error("while trying to get private field value of entity " + SearchCriteria.class, e);
            }

            for (String element : elements) {
                if (elements.indexOf(element) == elements.size() - 1) {
                    hibernateCriteria = hibernateCriteria.add(eq(element, fieldValue));
                } else {
                    hibernateCriteria = hibernateCriteria.createCriteria(element);
                }
            }
        }

        return getHibernateTemplate().findByCriteria(hibernateCriteria);
    }
1 голос
/ 23 сентября 2011

Нет, это невозможно. API Detached Criteria не позволяет - в лучшую или в худшую сторону - разрешать обнаружение, поэтому вы не сможете запросить у него «существующие» критерии.

Однако вы можете поддерживать собственную карту вложенных критериев по пути ассоциации. В псевдокоде:

Map<String, DetachedCriteria> criteriaMap = ...;

for ( ) { // loop over annotation criteria's "elements"
    DetachedCriteria existing = criteriaMap.get(fullPath);
    if (existing==null) {
        existing = parentCriteria.createCriteria(pathElement);
        criteriaMap.put(fullPath, existing);
    }
    existing.add(whateverCondition);
}
...