1. 简介

本文将探讨如何在 Spring Boot 应用中使用 Blaze Persistence 库。该库提供了丰富的 Criteria API,用于以编程方式构建 SQL 查询,支持添加各类过滤器、函数和逻辑条件。我们将涵盖项目配置、查询构建示例以及实体到 DTO 的映射实现。

2. Maven 依赖

pom.xml 中添加以下核心依赖:

<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-core-api-jakarta</artifactId>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-core-impl-jakarta</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-integration-hibernate-6.2</artifactId>
    <scope>runtime</scope>
</dependency>

⚠️ 注意:Hibernate 版本不同时,最后一个依赖可能需要调整。

3. 实体模型

定义两个通过一对多关联的实体类 PersonPost,使用 Hibernate 自动建表:

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private int age;

    @OneToMany(mappedBy = "author")
    private Set<Post> posts = new HashSet<>();
}
@Entity
public class Post {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

    private String content;

    @ManyToOne(fetch = FetchType.LAZY)
    private Person author;
}

4. Criteria API

作为 JPA Criteria API 的替代方案,Blaze Persistence 设计更友好易用,且支持多种 JPA 实现。

4.1. 配置

在配置类中声明 CriteriaBuilderFactory Bean:

@Autowired
private EntityManagerFactory entityManagerFactory;

@Bean
public CriteriaBuilderFactory createCriteriaBuilderFactory() {
    CriteriaBuilderConfiguration config = Criteria.getDefault();
    return config.createCriteriaBuilderFactory(entityManagerFactory);
}

4.2. 基础查询

两行代码即可完成全表查询:

List<Post> posts = builderFactory.create(entityManager, Post.class).getResultList();

✅ 关键点:

  • Post.class 参数同时定义了:
    • 查询结果类型
    • 隐式查询根
    • 自动生成 SELECTFROM 子句

生成的 JPQL:

SELECT post
FROM Post post;

4.3. WHERE 子句

通过链式调用添加条件,筛选年龄 18-40 岁且发表至少 2 篇文章的作者:

CriteriaBuilder<Person> personCriteriaBuilder = builderFactory.create(entityManager, Person.class, "p")
  .where("p.age")
    .betweenExpression("18")
    .andExpression("40")
  .where("SIZE(p.posts)").geExpression("2")
  .orderByAsc("p.name")
  .orderByAsc("p.id");

✅ 优势:

  • 直接支持函数调用(如 SIZE
  • 通过 whereOr/whereAnd 构建复合条件

复合条件示例(标题或作者名匹配):

CriteriaBuilder<Post> postCriteriaBuilder = builderFactory.create(entityManager, Post.class, "p")
  .whereOr()
    .where("p.title").like().value(title + "%").noEscape()
    .where("p.author.name").eq(authorName)
  .endOr();

4.4. FROM 子句

显式指定查询根可覆盖隐式设置:

CriteriaBuilder<Post> postCriteriaBuilder = builderFactory.create(entityManager, Post.class)
  .from(Person.class, "person")
  .select("person.posts");

此时 Post.class 仅定义返回类型,生成的 SQL 会自动添加 JOIN:

SELECT posts_1 
FROM Person person 
LEFT JOIN person.posts posts_1;

5. Entity-View 模块

解决实体与 DTO 的高效映射问题,通过接口定义投影结构。

5.1. Maven 依赖

添加以下依赖:

<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-entity-view-api-jakarta</artifactId>
</dependency>
<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-entity-view-impl-jakarta</artifactId>
</dependency>
<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-entity-view-processor-jakarta</artifactId>
</dependency>

5.2. 配置

声明 EntityViewManager Bean:

@Bean
public EntityViewManager createEntityViewManager(
  CriteriaBuilderFactory criteriaBuilderFactory, EntityViewConfiguration entityViewConfiguration) {
    return entityViewConfiguration.createEntityViewManager(criteriaBuilderFactory);
}

⚠️ 作用域需与 EntityManagerFactory 保持一致。

5.3. 映射定义

基础视图接口示例:

@EntityView(Post.class)
public interface PostView {
  
    @IdMapping
    Long getId();

    String getTitle();

    String getContent();
}

✅ 最佳实践:

  • 使用 @EntityView 注解绑定实体类
  • 通过 @IdMapping 优化 equals/hashCode 实现

自定义映射示例(标题大写):

@Mapping("UPPER(title)")
String getTitle();

扩展视图(包含作者信息):

@EntityView(Person.class)
public interface PersonView {
    @IdMapping
    Long getId();
    int getAge();
    String getName();
}

@EntityView(Post.class)
public interface PostWithAuthorView extends PostView {
    PersonView getAuthor();
}

查询应用示例:

CriteriaBuilder<Post> postCriteriaBuilder = builderFactory.create(entityManager, Post.class, "p")
  .whereOr()
    .where("p.title").like().value("title%").noEscape()
    .where("p.author.name").eq(authorName)
  .endOr();

CriteriaBuilder<PostWithAuthorView> postWithAuthorViewCriteriaBuilder =
  viewManager.applySetting(EntityViewSetting.create(PostWithAuthorView.class), postCriteriaBuilder);

生成的优化 SQL:

SELECT p.id AS PostWithAuthorView_id,
  p.author.id AS PostWithAuthorView_author_id,
  author_1.age AS PostWithAuthorView_author_age,
  author_1.name AS PostWithAuthorView_author_name,
  p.content AS PostWithAuthorView_content,
  UPPER(p.title) AS PostWithAuthorView_title
FROM com.baeldung.model.Post p
LEFT JOIN p.author author_1
WHERE p.title LIKE REPLACE(:param_0, '\\', '\\\\')
  OR author_1.name = :param_1

5.4. 集成 Spring Data

添加 Spring Data 集成依赖:

<dependency>
    <groupId>com.blazebit</groupId>
    <artifactId>blaze-persistence-integration-spring-data-3.1</artifactId>
</dependency>

配置类添加注解:

@EnableBlazeRepositories(basePackages = "com.example.repository")

Repository 接口定义:

@Repository
@Transactional(readOnly = true)
public interface PostViewRepository extends EntityViewRepository<PostWithAuthorView, Long> {
}

✅ 继承 EntityViewRepository 后自动获得 findAllfindOne 等常用方法。

6. 总结

本文演示了 Blaze Persistence 的核心配置与查询构建技巧。该库通过简洁的 API 设计和强大的映射能力,有效解决了传统 JPA Criteria API 的痛点。完整示例代码可在 GitHub 获取。


原始标题:Getting Started with Blaze Persistence