Skip to content
On this page

快速开始

项目 pom 中引入依赖

xml
<dependency>
    <groupId>cn.soboys</groupId>
    <artifactId>simplest-jpa-spring-boot-starter</artifactId>
    <version>1.2.0</version>
</dependency>

<!-- MySQL -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

在 SpringBoot 启动类或者配置类上通过 @EnableJPAQuery注解开启 simplest-jpa

java
@SpringBootApplication
@EnableJPAQuery
public class SpringbootJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootJpaApplication.class, args);
    }

}

到此你项目中就可以使用所有的功能了。

数据库配置

在项目中配置对应数据库连接

yml
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/rest-admin?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 10
      maximum-pool-size: 20
      idle-timeout: 600000
      max-life-time: 1800000

  jpa:
    hibernate:
      naming:
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
      ddl-auto: update # 控制是否可以基于程序中Entity的定义自动创建或者修改DB中表结构
    show-sql: true #控制是否打印运行时的SQL语句与参数信息
    database-platform: org.hibernate.dialect.MySQLDialect #数据库方言
    open-in-view: true
    properties:
      hibernate:
        enable_lazy_load_no_trans: true

定义对应entity 对应数据库表。JPA 会自动帮你生成数据库。

java
package cn.soboys.springbootjpa.entity;

import cn.soboys.springbootjpa.entity.base.BaseEntity;
import cn.soboys.springbootjpa.entity.dto.TitleVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/19 10:44
 * @webSite https://github.com/coder-amiao
 * 内容分类
 */
@Data
@Entity
@Table(name = "cms_category")
public class Category extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    /**
     * 标题
     */
    @Column(nullable = false, length = 64)
    @Schema(description = "标题")
    private String title;


    /**
     * @Embedded 用户映射数据库表到一个实体vo。
     */
    @Embedded
    @Schema(description = "标题信息")
    private TitleVo titleVo;

    /**
     * 描述
     */
    @Schema(description = "描述")
    private String described;

    /**
     * 图标
     */
    @Column( length = 32)
    @Schema(description = "图标",maxLength = 32)
    private String icon;

    /**
     * 图片
     */
    @Column( length = 32)
    @Schema(description = "图片",maxLength = 32)
    private String pic;

    /***
     * 引用关系不填写。默认对应主键。
     */
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE},fetch = FetchType.LAZY)
    @JoinTable(name = "cms_module_relation",
            joinColumns = @JoinColumn(name = "resource_id"),
            inverseJoinColumns = @JoinColumn(name = "module_id"))
    private Set<Module> modules=new HashSet<>();


    /**
     * 额外其他属性
     * @Transient 解绑和数据联系。属于实体类属性
     */
    @Transient
    private String other;


}

生成对应查询EntityPath

基于 QueryDSL 的APT 技术 在 maven 的 pom.xml 中引入对应的插件

xml
<plugin>
    <!--因为QueryDsl是类型安全的,所以还需要加上Maven APT plugin,使用 APT 自动生成Q类:-->
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>target/generated-sources/java</outputDirectory>
                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
        </execution>
    </executions>
</plugin>

然后通过 maven 编译项目。

会在你指定目录生成对应查询EntityPaht实体

简单查询

  1. 编写自己的Repository 继承通用BaseRepository
java
package cn.soboys.springbootjpa.repository;

import cn.soboys.simplestjpa.BaseRepository;
import cn.soboys.springbootjpa.entity.Category;
import org.springframework.stereotype.Repository;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/19 12:02
 * @webSite https://github.com/coder-amiao
 * 数据库 dao层。
 */
@Repository
public interface CategoryRepository extends BaseRepository<Category, Long{


}
  1. 编写自己的Service 继承通用Service
java
package cn.soboys.springbootjpa.service;

import cn.soboys.simplestjpa.IService;
import cn.soboys.springbootjpa.entity.Category;
import org.springframework.data.jpa.repository.Query;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/19 17:08
 * @webSite https://github.com/coder-amiao
 */
public interface ICategoryService extends IService<Category,Long> {



}

实现类

java
package cn.soboys.springbootjpa.service.impl;

import cn.soboys.simplestjpa.ServiceImpl;
import cn.soboys.springbootjpa.entity.Category;
import cn.soboys.springbootjpa.repository.CategoryRepository;
import cn.soboys.springbootjpa.service.ICategoryService;
import org.springframework.stereotype.Service;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/20 14:46
 * @webSite https://github.com/coder-amiao
 */
@Service
public class CategoryServerImpl extends ServiceImpl<CategoryRepository, Category, Long> implements ICategoryService {


}

这样你 service 有基础所有操作数据增删改查的方法

java
package cn.soboys.springbootjpa;

import cn.soboys.simplestjpa.UpdateWrapper;
import cn.soboys.springbootjpa.entity.Category;
import cn.soboys.springbootjpa.entity.QCategory;
import cn.soboys.springbootjpa.entity.dto.QTitleVo;
import cn.soboys.springbootjpa.service.ICategoryService;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAUpdateClause;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.text.StrUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/26 21:54
 * @webSite https://github.com/coder-amiao
 */
@SpringBootTest
@Slf4j
public class ServiceTest {
    @Autowired
    private ICategoryService categoryService;

    @Test
    void countByExample() {
        Category category = new Category();
        //category.setTitle("测试");
        long count = categoryService.count(Example.of(category));
        log.info("条件count{}", count);
    }

    @Test
    void getById() {
        Optional<Category> category = categoryService.getByIdOpt(6l);
        if (category.isPresent()) {
            log.info(category.get().toString());
        }
    }

    @Test
    void getOne() {
        QCategory qCategory = QCategory.category;
        QTitleVo vo=QTitleVo.titleVo;
        Predicate query=vo.subTitle.eq("batch1");
        Category category = categoryService.getOne(query);
        log.info(category.toString());
    }

    @Test
    void getPageQuery() {
        QCategory qCategory = QCategory.category;
        PageRequest pageRequest = PageRequest.of(0, 20); //第一页从零开始
        Predicate query = qCategory.title.like("%" + "batch" + "%");
        Page<Category> categoryList = categoryService.page(pageRequest, query);
        log.info("数量{}", categoryList.getContent().size());
    }

    @Test
    void getPage() {
        QCategory qCategory = QCategory.category;

      // categoryService.getJPAQueryFactory().select().where(qCategory.)
    }


    @Test
    void save() {
        Category c = new Category();
       // c.setTitle("保存");
        categoryService.save(c);
    }

    @Test
    void deleteById() {
        categoryService.removeById(6l);
    }

    @Test
    void deleteAll() {
        List<Long> ids = new ArrayList<>();
        ids.add(6l);
        ids.add(7l);
        Boolean flag = categoryService.removeByIds(ids);
    }

    /**
     * 实体ID对应存在更新否则添加
     */
    @Test
    void saveOrUpdate() {
        Category c = new Category();
       // c.setTitle("保存");
        categoryService.saveOrUpdate(c);
    }


    @Test
    @Rollback(value = false)
    @Transactional
    void updateChain() {
        QCategory qCategory = QCategory.category;
        categoryService.updateChain(qCategory)
                .set(qCategory.title, "测试jpa")
                .where(qCategory.id.eq(6l)).execute();
    }


    @Test
    @Rollback(value = false)
    @Transactional
    void update() {
        QCategory qCategory = QCategory.category;
        JPAUpdateClause updateWrapper = UpdateWrapper.of(qCategory);
        updateWrapper.set(qCategory.title, "bh").where(qCategory.id.eq(6l));

        Boolean flag = categoryService.update(updateWrapper);

        log.info("更新{}", flag);
    }

    @Test
    @Rollback(value = false)
    @Transactional
    void updateIgnoreNull() {
        Category category = new Category();
        category.setId(6l);
       // category.setSubTitle("忽略");
        //Category category1 = categoryService.update(category, true);  //会自动忽略实体空属性。

        //category.setTitle("");
        Category category1 = categoryService.update(category, true, new String[]{"title"});  //自定义不忽略字段,
        log.info("更新{}", category1);
    }

    @Test
    void selectQueryChain() {
        QCategory qCategory = QCategory.category;
        List<String> categoryList = categoryService.queryChain()
                .select(qCategory.title)
                .from(qCategory).fetch();
        log.info("返回条数{}", categoryList.size());
    }


    @Test
    void selectQuery() {
        QCategory qCategory = QCategory.category;
        BooleanBuilder booleanBuilder = new BooleanBuilder();

        String subTitle = "88";
        if (StrUtil.isNotEmpty(subTitle)) {
            booleanBuilder.and(qCategory.described.eq("88"));
        }
        long id = 6l;
        if (!StrUtil.isBlankIfStr(id)) {
            booleanBuilder.and(qCategory.id.eq(6l));
        }
        List<Category> categories = categoryService.list(booleanBuilder);
        log.info("返回条数{}", categories.size());
    }

}