有人可以告诉我一个如何使用 criteriaBuilder 进行 Hibernate 查询并连接到子查询的示例吗
这是一个简单的例子:
select idSchool, name from user left join (select idSchool from student where age < 15) as NewTable on idSchool = idSchool
Run Code Online (Sandbox Code Playgroud)
谢谢
我正在尝试使用 JPA 和 Criteria API 但没有元模型来构建动态查询。
与表:
Foo:
ID
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
Bar:
ID FooID Number
1 2 44
2 2 55
3 3 55
Run Code Online (Sandbox Code Playgroud)
我想检索所有 Foo 实体,其中没有匹配的 Bar 具有编号 44。(期望 Foo 1, 3, 4)
SQL 应该看起来像这样:
select distinct *
from Foo foo0_
left join Bar bar0_ on foo0_.ID=bar0_.FooID and bar0_.Number=44
where bar0__.id is null;
Run Code Online (Sandbox Code Playgroud)
我的代码看起来像这样:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);
Root<Foo> fooRoot = cq.from(Foo.class);
cq.select(fooRoot).distinct(true);
List<Predicate> allPredicates = new ArrayList<Predicate>();
List<Predicate> orPredicates = new ArrayList<Predicate>(); …Run Code Online (Sandbox Code Playgroud) 我需要使用Spring Boot REST和Spring Data JPA使用 Criteria API 来实现复杂的搜索功能。我需要提供如下所示的 RPI
,/college?select=*&where=name:DemoCollege并输入[1,2,3]location:LAstaff{firstName:foo, lastName:boo, workExp>10}
Collage 对象有name、location、type字段和staff列表。它有onetomany关系,Staff所以College可以有一名或多名工作人员。
基于 uri,我需要使用 criteria api 构建查询。
我发现实现该toPredicate()方法非常复杂org.springframework.data.jpa.domain.Specification。有没有这样的例子来处理如此复杂的搜索过滤器?
提前致谢。
我正在创建一个 Spring Boot 应用程序,其中包含产品、类别、机械、使用位置等实体。所有这些实体的共同点是它们都有一个名为 name 的 String 属性,并且可以使用 name 从 UI 中过滤。我已经编写了一个使用名称进行过滤的产品规范,并且它正在工作。下面是代码
public final class ProductSpecifications
{
public static Specification<Product> whereNameContains(String name)
{
Specification<Product> finalSpec = (Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb)
-> cb.like(root.get(Product_.PRODUCT_NAME), "%"+name+"%");
return finalSpec;
}
public static Specification<Product> whereNameEqauls(String name)
{
Specification<Product> finalSpec = (Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb)
-> cb.equal(root.get(Product_.PRODUCT_NAME), name);
return finalSpec;
}
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是我必须再次编写相同的代码来过滤其他实体,唯一的区别是类名(Product)、字段名称(Product_NAME)和方法的返回类型。我可以创建一个通用类和方法吗?我可以将类名和字段名作为参数传递给它,并返回相应返回类型的规范。
我遇到了Subqueries.exists标准的问题.
我有以下内容:
DetachedCriteria criteria = DetachedCriteria.forClass(Expense.class, "mainExpense")
.add(Restrictions.eq("group", group))
.addOrder(Order.desc("created"));
if (all) {
criteria.add(
Restrictions.or(
Restrictions.eq("status", ExpenseStatus.PENDING),
Restrictions.eq("status", ExpenseStatus.COMPLETE)
));
} else {
criteria.add(Restrictions.eq("status", ExpenseStatus.PENDING));
}
if (user != null) {
DetachedCriteria userSubCriteria = DetachedCriteria.forClass(UserExpense.class, "userExpense")
.add(Restrictions.eq("userExpense.primaryKey.user", user))
.add(Restrictions.eq("userExpense.primaryKey.expense", "mainExpense"))
.setProjection(Projections.property("userExpense.primaryKey"));
criteria.add(Subqueries.exists(userSubCriteria));
}
return getHibernateTemplate().findByCriteria(criteria);
Run Code Online (Sandbox Code Playgroud)
如果我传递一个空用户(不使用Subqueries.exists),它可以正常工作并返回有效的费用项目.如果我给用户如果给我以下内容:
org.springframework.orm.hibernate3.HibernateSystemException:无法通过Expense.id的反射getter获取字段值; 嵌套异常是org.hibernate.PropertyAccessException:无法通过Expense.id的反射getter获取字段值
并在日志中降低:
无法将java.lang.Integer字段Expense.id设置为java.lang.String
有没有人知道我做错了什么?
鉴于以下情况:
CriteriaQuery<SomeDTO> cQuery;
CriteriaBuilder cb;
Root<SomeClass> r;
...
cQuery.select(cb.construct(SomeDTO.class,
"FIXED VALUE",
r.get(SomeClass_.someValue)
));
Run Code Online (Sandbox Code Playgroud)
有没有办法使用 JPA 标准 api 和静态元模型来创建一个选择,它为一列返回一个固定值?相应的 SQL 应该类似于
SELECT 'FIXED VALUE', someValue FROM someClassTable WHERE ...;
Run Code Online (Sandbox Code Playgroud)
提前致谢!
我想通过Hibernate Criteria Query的子对象列表查询Parent对象.我知道如何使用孩子的ID但不直接使用实体.
这有效:
List<Long> listOfChildLongChildIds = new ArrayList<Long>();
listOfChildLongChildIds.add(new Long(1));
listOfChildLongChildIds.add(new Long(2));
Criteria criteria = getSession().createCriteria(Parent.class);
Criteria criteriaChilds = criteria.createCriteria("childs");
criteriaChilds.add(Restrictions.in("id", listOfChildLongChildIds));
Run Code Online (Sandbox Code Playgroud)
但是当列表包含这样的子对象/实体时,如何做到这一点:
List<Child> listOfChildEntities = new ArrayList<Child>();
listOfChildEntities.add(QueryChildFromDatabse);
listOfChildEntities.add(QueryChildFromDatabse);
Run Code Online (Sandbox Code Playgroud)
(这意味着我不使用孩子的ID而只使用Entitiy本身.原因是否则我将不得不遍历我的孩子列表并提取所有ID并将它们放入我认为最不可能的列表中.但我无法找到任何有关如何按实体列表本身查询的信息):
然后上面的代码使用
criteriaChilds.add(Restrictions.in("id",listOfChildEntities));
Run Code Online (Sandbox Code Playgroud)
将抛出异常:
孩子不能被强制转换为java.lang.Long
使用Conjunctions和Disjunctions时遇到问题.我的程序Criterion从ui 接收任意数量的过滤元素(每个过滤元素代表一个),并打算将它们链接在一起作为AND或OR.
所以例如我可以有3个这样的元素(我代表Criterion一个字母):
a OR b AND c
Run Code Online (Sandbox Code Playgroud)
我的代码看起来像这样:
// ...
Criteria rootCriteria = createCriteria(entityClass);
Conjunction conjunction = Restrictions.conjunction();
Disjunction disjunction = Restrictions.disjunction();
boolean isFirst = true;
for (InternalFilterElement element : elements) {
if (isFirst) {
isFirst = false;
rootCriteria.add(createCriterion(element.getFilterRelation(), element.getValue()));
} else if (InternalFilterOperand.AND.equals(element.getInternalFilterOperand())) {
addCriterionToJunction(conjunction, element);
} else {
addCriterionToJunction(disjunction, element);
}
}
rootCriteria.add(disjunction);
rootCriteria.add(conjunction);
// ...
Run Code Online (Sandbox Code Playgroud)
我的问题是我总是得到a AND b AND c一些不必要的括号.
我真正想知道的是,我是否使用了错误的工具来完成这项任务?我该如何混合AND …
我想在我们使用的多选jpa条件查询中选择特定格式的日期
select to_char(tn.dbdate,'yyyy-MM-dd') from transaction tn在oracle.
我可以使用
query.multiselect(cb.function("TO_CHAR",String.class,transaction.get("dbdate")) );
但这会以数据库格式返回日期,即
Wed Apr 2 12:20:50 2014
但是如何以特定的日期格式获取此信息
'yyyy-MM-dd'
我正在研究JPA标准api,我的数据库包含Employee表.我试图找到所有薪水第二高的员工.我能够成功编写JPQL,如下所示.
SELECT e FROM Employee e WHERE e.salary = (SELECT MAX(emp.salary) FROM Employee emp WHERE emp.salary < (SELECT MAX(employee.salary) FROM Employee employee) )
Run Code Online (Sandbox Code Playgroud)
但现在我正在尝试将其转换为标准api并尝试跟随.
CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
Root<Employee> e1 = c.from(Employee.class);
c.select(e1);
Subquery<Number> sq = c.subquery(Number.class);
Root<Employee> e2 = sq.from(Employee.class);
sq.select(cb.max(e2.<Number> get("salary")));
Subquery<Number> sq1 = sq.subquery(Number.class);
Root<Employee> e3 = sq1.from(Employee.class);
sq1.select(cb.max(e3.<Number> get("salary")));
c.where(cb.lessThan(e2.<Number>get("salary"), e3.<Number>get("salary")));// error here
c.where(cb.equal(e1.get("salary"), sq));
Run Code Online (Sandbox Code Playgroud)
我得到参数与lessThan方法不兼容的错误.我不明白如何才能解决这个问题.我的做法是对的吗?
编辑: - 在Mikko回答后更新问题.
上面提供的jpql提供了以下结果,即薪水第二高的员工.
Harish Taware salary 4000000.0
Nilesh Deshmukh salary 4000000.0
Deodatta Chousalkar salary 4000000.0
Deodatta Chousalkar …Run Code Online (Sandbox Code Playgroud) criteria-api ×10
hibernate ×5
java ×5
jpa ×5
spring ×2
spring-boot ×2
date ×1
jpa-2.0 ×1
metamodel ×1
predicate ×1
spring-rest ×1
sql ×1