图源:
JPA 中的查询(Query)有三种类型:
-
Query,用 Java 持久性查询语言(JPQL,Java Persistence Query Language)编写。
-
NativeQuery,纯 SQL 编写。
-
Criterial API Query,用编程的方式编写。
为了介绍这些查询,这里定义一个实体类:
public class Student {
strategy = GenerationType.IDENTITY)
( private Long id;
max = 45)
( unique = true)
( private String name;
private LocalDate birthDay;
max = 255)
( private String address;
}
Query
可以通过Session.createQuery
或EntityManager.createQuery
创建一个 JPQL 查询语句:
Query<Student> query = session.createQuery("select s from Student s where s.name=:name", Student.class);
query.setParameter("name", "icexmoon");
Student student = query.getSingleResult();
JPQL 中不使用表名称,而是用实体名称取代。相应的,也不使用表字段,用实体属性名称取代。
JPQL 中的参数用:
+参数名称的方式定义。
创建了 JPQL 查询对象后,可以通过Query.setParameter
设置 JPQL 中定义的参数的值。
最后,通过Query.getSingleResult
方法可以执行查询并获取一条结果,或者用Query.getResultList
获取所有结果集。
NamedQuery
对于需要重复使用的 JPQL 语句,可以定义被称作 NamedQuery 的查询语句。这些 NamedQuery 可以在实体类上用@NamedQuery
定义:
name = "Student.findByName",
( query = "select s from Student s where s.name=:name")
public class Student {
// ...
}
需要注意的是,NamedQuery 的名称(@NamedQuery(name=xxx)
)必须保证唯一。
通过Session.createNamedQuery
就可以用定义好的 NamedQuery 创建查询对象:
Student student = session.createNamedQuery("Student.findByName", Student.class)
.setParameter("name", "icexmoon")
.getSingleResult();
@NamedQuery
是可重复注解,可以用多个@namedQuery
定义多条 NamedQuery:
name = "Student.findByName",
( query = "select s from Student s where s.name=:name")
name = "Student.findAll",
( query = "select s from Student s")
name = "Student.findByBirthDay",
( query = "select s from Student s where s.birthDay>:birthDay")
public class Student {
// ...
}
对于不支持重复注解的 Java 8 之前的版本,可以使用@NamedQueries
注解进行包裹。
NativeQuery
可以用 NativeQuery 执行纯 SQL 编写的查询。
用Session.createNativeQUery
可以构建相应的查询对象:
String targetName = "icexmoon";
NativeQuery<Student> nativeQuery = session.createNativeQuery("select * from student where name=:name", Student.class);
nativeQuery.setParameter("name", targetName);
Student student = nativeQuery.getSingleResult();
Assertions.assertEquals(targetName, student.getName());
Criteria API Query
所谓的条件 API(Criteria API)指的是可以帮助我们构建 SQL 查询条件的一组 API,可以利用这些 API 来构建查询语句并执行。
调用示例:
HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
JpaCriteriaQuery<Student> query = criteriaBuilder.createQuery(Student.class);
JpaRoot<Student> from = query.from(Student.class);
String targetName = "icexmoon";
query = query.select(from)
.where(criteriaBuilder.equal(from.get("name"), targetName));
Student student = session.createQuery(query)
.getSingleResult();
Assertions.assertEquals(targetName, student.getName());
需要先通过Sesstion.getCriteriaBuilder
获取一个HibernateCriteriaBuilder
对象帮助构建条件 API 语句。然后通过HibernateCriteriaBuilder.createQuery
创建条件查询对象JpaCriteriaQuery
。之后通过JpaCriteriaQuery.select
、JpaCriteriaQuery.where
等一系列 API 构建 SQL 内容,并最终通过Session.createQuery
利用构建好的条件 API Query 创建 JPQL 查询对象,并执行查询。
对比
用 Query 或 NativeQuery 构建查询语句相对简单,前者相比后者,更具移植性(屏蔽了具体数据库产品的差异)和通用性,并且可以利用 JPA 层的缓存和过滤器等特性,但缺点是无法使用具体数据库的特异化查询语句。
Criteria API Query 构建查询语句相对麻烦很多,优点是从写法上杜绝了可能的 SQL 语法错误,以及在某些特殊情况下用编程方式构建 SQL 的可能,缺点是写法相对复杂。
The End,谢谢阅读。
可以从
文章评论