使用子条件创建动态休眠条件查询

发布于 2024-12-06 06:01:33 字数 1095 浏览 1 评论 0原文

我有一个 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]));
    }

我想删除这个“开关”。可以通过(我现在不这样做)获得已经添加的标准,例如通过“名称”,并为其添加新的子标准。

I have a Java class which has some field annotated with @SearchCriteria(criteria = "class1.class2.field"). criteria parameter inside annotation means for with class this field should be set as hibernate criteria, it mean that, if field marked for example:

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

I want dynamicly create hibernate criteria with looks like

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

Problem is than I can not set another criteria to already added, it mean I should check annotation criteria option.

      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]));
    }

I want to remove this "swith". It is possible to get already added criteria by, I dont now, for example by "name" and that add new subcriteria for it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

埖埖迣鎅 2024-12-13 06:01:33

不,这是不可能的。 分离条件 API 不 - 对于更好或更坏 - 允许发现,因此您将无法向其询问“现有”标准。

但是,您可以做的是通过关联路径维护您自己的嵌套条件映射。在伪代码中:

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);
}

No, it's not possible. Detached Criteria API does not - for better or worse - allow for discovery, so you won't be able to ask it for "existing" criteria.

What you can do, however, is maintain your own map of nested criteria by association path. In pseudo-code:

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);
}
九公里浅绿 2024-12-13 06:01:33

我找到了这个问题的更多“好”解决方案。
首先创建一些 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);
    }

I find out more "nice" solution for this issue.
First of all create some searchCriteria class, for example:

public class SearchCriteria {

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

    public Integer getSomeId() {
        return someId;
    }

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

And custom annotation:

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

    boolean optional() default true;
}

And in DAO class:

@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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文