从零开始 Spring Boot 65:JPA 中的查询语句

从零开始 Spring Boot 65:JPA 中的查询语句

spring boot

图源:简书 (jianshu.com)

JPA 中的查询(Query)有三种类型:

  • Query,用 Java 持久性查询语言(JPQL,Java Persistence Query Language)编写。
  • NativeQuery,纯 SQL 编写。
  • Criterial API Query,用编程的方式编写。

为了介绍这些查询,这里定义一个实体类:

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @NotBlank
    @Length(max = 45)
    @Column(unique = true)
    private String name;

    @NotNull
    private LocalDate birthDay;

    @NotNull
    @NotBlank
    @Length(max = 255)
    private String address;
}

Query

可以通过Session.createQueryEntityManager.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定义:

@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:

@NamedQuery(name = "Student.findByName",
        query = "select s from Student s where s.name=:name")
@NamedQuery(name = "Student.findAll",
        query = "select s from Student s")
@NamedQuery(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.selectJpaCriteriaQuery.where等一系列 API 构建 SQL 内容,并最终通过Session.createQuery利用构建好的条件 API Query 创建 JPQL 查询对象,并执行查询。

对比

用 Query 或 NativeQuery 构建查询语句相对简单,前者相比后者,更具移植性(屏蔽了具体数据库产品的差异)和通用性,并且可以利用 JPA 层的缓存和过滤器等特性,但缺点是无法使用具体数据库的特异化查询语句。

Criteria API Query 构建查询语句相对麻烦很多,优点是从写法上杜绝了可能的 SQL 语法错误,以及在某些特殊情况下用编程方式构建 SQL 的可能,缺点是写法相对复杂。

The End,谢谢阅读。

可以从这里获取本文的完整示例代码。

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值