Quarkus - 集成QueryDsl

350 阅读2分钟

Querydsl是一个非常强大的Java查询框架,可以帮助开发者简化和优化数据库查询操作。Querydsl可以让开发者使用Java代码来编写SQL查询,从而避免了字符串拼接带来的错误风险,并提高了代码的可读性和可维护性。其还支持各种高级查询功能,例如连接、子查询、聚合等,并可以生成各种数据库方言的SQL语句。

快速开始

1.引入依赖

  // quarkus orm 依赖
  implementation 'io.quarkus:quarkus-hibernate-orm'
  implementation 'io.quarkus:quarkus-jdbc-postgresql'
  
  // 若 springboot 可引入 jpa依赖
  //implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

  // querydsl依赖,若非springboot3.x或quarkus3.x,可去掉末尾的 `:jakarta`
  compileOnly 'com.querydsl:querydsl-apt:5.0.0:jakarta'
  implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
  annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
  annotationProcessor 'jakarta.persistence:jakarta.persistence-api:3.1.0'

2.配置数据源

quarkus.datasource.jdbc.url=jdbc:postgresql://192.168.100.100:5432/test?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
quarkus.datasource.username=root
quarkus.datasource.password=root

# 表创建策略,可用值 none, create, drop-and-create, drop, update, validate
quarkus.hibernate-orm.database.generation=update
# springboot 则是
#spring.jpa.hibernate.ddl-auto=update

# quarkus 开启日志
%dev.quarkus.log.category."org.hibernate.SQL".min-level=DEBUG
%dev.quarkus.log.category."org.hibernate.SQL".level=DEBUG
# springboot 则是
#spring.jpa.show-sql=true

3.配置类

即使用 hibernateentityManager 构建 JPAQueryFactory 即可。

public class QueryDslConfig {
  @Inject EntityManager entityManager;

  @Singleton
  public JPAQueryFactory jpaQueryFactory() {
    return new JPAQueryFactory(entityManager);
  }
}

4.实体类

@Data
@Entity // 必加注解 jakarta.persistence.Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {

  @Id
  @GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
  String id;

  String fullName;
}

5.增删改查

Querydsl 的查询用法和sql语句基本一致,所以不查阅文档基本也能知道如何写查询条件。

@Path("/user")
public class UserResource {
    @Inject JPAQueryFactory jpaQueryFactory;
    @GET
    public void test() {
        // QUser.user 为自动生成,若没有请重新编译项目

        // 查询
        jpaQueryFactory.selectFrom(QUser.user)
                       .where(QUser.user.id.eq("1"))
                       .fetchOne();
        jpaQueryFactory.selectFrom(QUser.user)
                       .where(QUser.user.name.like("1"))
                       .fetch();
        // 新增
        jpaQueryFactory.insert(QUser.user).values(new User()).execute();
        // 也可以直接使用hibernate的 entityManager.persist(entity);

        // 修改
        jpaQueryFactory.update(QUser.user)
                       .set(QUser.user.name,"zhangsan")
                       .where(QUser.user.id.eq("1"))
                       .execute();

        // 删除
        jpaQueryFactory.delete(QUser.user).where(QUser.user.id.eq("1")).execute();
    }
}

通用 Repository

1.增加 Repository

public abstract class Repository<T> {
  @Inject EntityManager entityManager;
  @Inject JPAQueryFactory jpaQueryFactory;

  protected abstract EntityPathBase<T> get();

  public JPAQuery<T> select() {
    return jpaQueryFactory.selectFrom(get());
  }

  public <R extends T> JPAQuery<R> select(Expression<R> select) {
    return jpaQueryFactory.select(select).from(get());
  }

  public JPADeleteClause delete() {
    return jpaQueryFactory.delete(get());
  }

  public void persist(T entity) {
    entityManager.persist(entity);
  }

  public void persist(List<T> entity) {
    int i = 0;
    for (T t : entity) {
      entityManager.persist(t);
      i++;
      if (i % 1000 == 0) {
        entityManager.flush();
        entityManager.clear();
      }
    }
    if (i % 1000 != 0) {
      entityManager.flush();
      entityManager.clear();
    }
  }

  public Page<T> page(Page<?> page, Predicate... where) {
    if (page == null) {
      page = new Page<T>();
    }
    if (page.getCurrent() == 0) {
      page.setCurrent(1);
    }
    if (page.getPageSize() == 0) {
      page.setPageSize(10);
    }
    long count =
        Optional.ofNullable(
                jpaQueryFactory.select(get().count()).from(get()).where(where).fetchOne())
            .orElse(0L);
    var sql =
        jpaQueryFactory
            .select(get())
            .from(get())
            .where(where)
            .offset((page.getCurrent() - 1) * page.getPageSize())
            .limit(page.getPageSize());
    return Page.<T>builder()
        .current(page.getCurrent())
        .pageSize(page.getPageSize())
        .total(count)
        .records(sql.fetch())
        .build();
  }

  // 还需要什么方法可自行扩展
}

2.编写 UserRepository

User 为例,其他表也添加相应 xxxRepository 即可

@Singleton
public class UserRepository extends Repository<User> {
  @Override
  protected EntityPathBase<User> get() {
    return QUser.user;
  }
}

3.使用

@Path("/user")
class UserResource {
    @Inject
    UserRepository userRepository;

    @GET
    @Path("/all")
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> all() {
        return userRepository.select().fetch();
    }
}

博客内容遵循:署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本文永久链接是:seepine.com/quarkus/que…