Appearance
快速开始
项目 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实体
简单查询
- 编写自己的
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{
}
- 编写自己的
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());
}
}