搜索数据库中的关键字

时间:2014-05-13 14:04:58

标签: java sql jpa eclipselink named-query

我正在使用Eclipselink并且在JPA NamedQueries方面遇到了棘手的问题。

我的数据库表包含一个来自VARCHAR类型的列,并将逗号分隔的关键字列表存储为一个String。

如何在JPA中创建NamedQuery来搜索theese关键字? 我想给出一个Strings列表作为参数,因此我想得到一个对象列表,其中关键字列表包含参数列表中的一个字符串。 可能如下:

List<String> keywordList = new ArrayList<String>();
keywordList.add("test");
keywordList.add("car");    

List<Object> result = em.createNamedQuery("findObjectByKeywords", Object.class)
                            .setParameter("keywords", keywordList)
                            .getResultList();

不幸的是,我不是一个如此庞大的数据库/ SQL专家。也许有人可以帮助我?

我希望你能理解我的问题。

修改 我正在开发Weblogic 10.3.6,这意味着我无法使用JPA 2.0功能。

EDIT2: 我在Oracle Enterprise Pack for Eclipse的帮助下设法在我的Weblogic Server中激活了JPA 2.0。问题解决了,我想。

1 个答案:

答案 0 :(得分:3)

有效的JPA2.0

正如Bhesh评论的那样,简单的JPQL无法实现。生成的SQL必须包含类似于以下内容的 where 子句:

where keywords like '%keyword1%' or keywords like '%keyword2%' or ... or keywords like '%keywordN%'

这意味着:我们需要一个循环!

你可以尝试自己建立一个JPQL,就像Bhesh在他的第一条评论中所建议的那样,尽管他也表示这不是一个好主意。但不要担心 - JPA还提供Criteria API,在这种情况下会派上用场。因此,虽然您不会有命名查询,但您仍然可以通过这种方式使用JPA:

public List<YourEntity> findAllByKeywords(List<String> keywords){
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<YourEntity> query = builder.createQuery(YourEntity.class);
    Root<YourEntity> root = query.from(YourEntity.class);

    List<Predicate> predicates = new LinkedList<>();
    for (String keyword : keywords) {
        predicates.add(builder.like(root.<String>get("keywords"), "%" + keyword + "%"));
    }

    return entityManager.createQuery(
            query.select(root).where(
                    builder.or(
                            predicates.toArray(new Predicate[predicates.size()])
                    )
            ))
            .getResultList();
}

或(与番石榴总是稍微好一点)

public List<YourEntity> findAllByKeywords(List<String> keywords){
    final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<YourEntity> query = builder.createQuery(YourEntity.class);
    final Root<YourEntity> root = query.from(YourEntity.class);
    return entityManager.createQuery(
            query.select(root).where(
                    builder.or(
                            transform(keywords, toPredicateFunction(builder, root)).toArray(new Predicate[]{})
                    )
            ))
            .getResultList();
}

private Function<String, Predicate> toPredicateFunction(final CriteriaBuilder builder, final Root<YourEntity> root) {
    return new Function<String, Predicate>() {
        @Override
        public Predicate apply(String input) {
            return builder.like(root.<String>get("keywords"), "%" + input + "%");
        }
    };
}