简体   繁体   English

具有数量可变的OR LIKE子句的休眠条件

[英]Hibernate criteria with variable amount of OR LIKE clauses

I am fairly new to hibernate, and at the moment struggeling with firing a query with the use of criteria. 我刚进入休眠状态,此刻正在努力使用条件触发查询。

What i want to achieve is, selecting all records that contain a certain string in either the first or lastname columns. 我要实现的是,选择在firstname或lastname列中包含某个字符串的所有记录。

Here is what I have. 这就是我所拥有的。 It should give a better idea. 它应该给出一个更好的主意。

Session session = HibernateUtil.openSession();
    Criteria criteria = session.createCriteria(Contact.class);

    if(keywords != null) {
        for(String keyword : keywords) {
            if(keyword != null && keyword.length() > 0) {
                criteria.add(Restrictions.like("firstName", keyword, MatchMode.ANYWHERE));
                criteria.add(Restrictions.or(Restrictions.like("lastName", keyword, MatchMode.ANYWHERE), null));
            }
        }
    }

    searchMatches = criteria.list();

so in the end the query should be something along the lines of: 因此,最后查询应该类似于以下内容:

SELECT * FROM contacts WHERE (firstname LIKE '%oe% OR lastname LIKE '%oe%'), and if multiple keywords are given, something like: SELECT * FROM从联系人所在的位置(名字为“%oe%”或姓氏为“%oe%”),如果给出多个关键字,则类似:

SELECT * FROM contacts WHERE (firstname LIKE '%oe% OR lastname LIKE '%oe%') OR (firstname LIKE '%roo% OR lastname LIKE '%roo%') 选择*从联系人所在的位置(姓氏为“%oe%”或姓氏为“%oe%”)或(姓氏为“%roo%”或姓氏为“%roo%”)

this would select the record containing "oe" inside either the first or lastname columns. 这将选择在“姓”或“姓”列中包含“ oe”的记录。 How ever I get a crash with the code when criteria.list(); 当Criteria.list();出现代码崩溃时, is run. 运行。

Here is the stack trace. 这是堆栈跟踪。 I can not figure out what it is I am doing wrong. 我不知道我在做什么错。

Caused by: java.lang.NullPointerException
at org.hibernate.criterion.LogicalExpression.toSqlString(LogicalExpression.java:60)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:419)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:123)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:92)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:93)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1464)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374)
at com.joey.wishlist.dao.impl.ContactDAOImpl.searchContacts(ContactDAOImpl.java:34)
at com.joey.wishlist.services.impl.ContactServiceImpl.searchContacts(ContactServiceImpl.java:22)
at com.joey.wishlist.presenters.ContactSearchPresenter.search(ContactSearchPresenter.java:75)

EDIT: I am one step closer. 编辑:我更近一步。

I fixed the error. 我修复了错误。 The error was caused by a malfunctioning or. 该错误是由故障或引起的。

The code now looks like this: 现在的代码如下所示:

        if(keywords != null) {
        for(String keyword : keywords) {
            if(keyword != null && keyword.length() > 0) {
                criteria.add(
                        Restrictions.or(
                            Restrictions.like("lastName", keyword, MatchMode.ANYWHERE), 
                            Restrictions.like("firstName", keyword, MatchMode.ANYWHERE)
                        ));
            }
        }
    }

Which produces this query, which is almost what i want. 哪个产生这个查询,这几乎是我想要的。 I just want the "AND" to be "OR". 我只希望“ AND”为“ OR”。 So: 所以:

Hibernate: 
/* criteria query */ select
    this_.id as id0_0_,
    this_.firstname as firstname0_0_,
    this_.lastname as lastname0_0_ 
from
    contactmanager this_ 
where
    (
        this_.lastname like ? 
        or this_.firstname like ?
    ) 
    and (
        this_.lastname like ? 
        or this_.firstname like ?
    )

I want to be: 我想成为:

Hibernate: 
/* criteria query */ select
    this_.id as id0_0_,
    this_.firstname as firstname0_0_,
    this_.lastname as lastname0_0_ 
from
    contactmanager this_ 
where
    (
        this_.lastname like ? 
        or this_.firstname like ?
    ) 
    or ( //Notice difference here
        this_.lastname like ? 
        or this_.firstname like ?
    )

Every time you call criteria.add , it adds an and to your statement. 每次您调用criteria.add ,它都会在您的声明中添加and What you want to to create a disjunction: 您要创建析取的内容:

Disjunction matchDisjunction = Restrictions.disjunction()
for(String keyword : keywords) {
            if(keyword != null && keyword.length() > 0) {
                matchDisjunction.add(
                        Restrictions.or(
                            Restrictions.like("lastName", keyword, MatchMode.ANYWHERE), 
                            Restrictions.like("firstName", keyword, MatchMode.ANYWHERE)
                        ));
            }
        }
criteria.add(matchDisjunction);

Or simply: 或者简单地:

Disjunction matchDisjunction = Restrictions.disjunction()
for(String keyword : keywords) {
            if(keyword != null && keyword.length() > 0) {
                matchDisjunction.add( Restrictions.like("lastName", keyword, MatchMode.ANYWHERE) );
                matchDisjunction.add( Restrictions.like("firstName", keyword, MatchMode.ANYWHERE) );
            }
        }
criteria.add(matchDisjunction);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM