SpringBoot整合系列-整合JPA
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9959865.html
SpringBoot整合JPA进行数据库开发
步骤
第一步:添加必要的jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
第二步:添加必要的配置
spring.datasource.url = jdbc\:h2\:file\:D\:\\testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username = sa
spring.datasource.password = sa
spring.datasource.driverClassName =org.h2.Driver
第三步:添加实体,并添加注解
@Entity
@Table(name = "USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int useId;
@Column
private String useName;
@Column
private UseSex useSex;
@Column
private int useAge;
@Column(unique = true)
private String useIdNo;
@Column(unique = true)
private String usePhoneNum;
@Column(unique = true)
private String useEmail;
@Column
private LocalDateTime createTime;
@Column
private LocalDateTime modifyTime;
@Column
private UseState useState;
}
第四步:添加持久层
@Repository
public interface UserRepository extends JpaRepository {
}
注意:
继承自JpaRepository的持久层可以直接使用其定义好的CRUD操作,其实只有增删查操作,关于修改的操作还是需要自定义的。
第五步:持久层的使用
@Service
public class UserService {
@Autowired
private UserRepository repository;
public ResponseEntity addUser(final User user) {
return new ResponseEntity<>(repository.save(user),HttpStatus.OK);
}
}
注意:其实在JpaRepository中已经定义了许多方法用于执行实体的增删查操作。
JPA高级功能
方法名匹配
在UserRepository中定义按照规则命名的方法,JPA可以将其自动转换为SQL,而免去手动编写的烦恼,比如定义如下方法:
User getUserByUseIdNo(String useIdNo);
JPA会自动将其转换为如下的SQL:
select * from USER where use_id_no = ?
下面简单罗列方法命名规则:
| 关键字 | 例子 | sql |
|---|---|---|
| And | findByNameAndAge | ...where x.name=?1 and x.age=?2 |
| Or | findByNameOrAge | ...where x.name=?1 or x.age=?2 |
| Between | findByCreateTimeBetween | ...where x.create_time between ?1 and ?2 |
| LessThan | findByAgeLessThan | ...where x.age < ?1 |
| GreaterThan | findByAgeGreaterThan | ...where x.age > ?1 |
| IsNull | findByAgeIsNull | ...where x.age is null |
| IsNotNull,NotNull | findByAgeIsNotNull | ...where x.age not null |
| Like | findByNameLike | ...where x.name like ?1 |
| NotLike | findByNameNotLike | ...where x.name not like ?1 |
| OrderBy | findByAgeOrderByNameDesc | ...where x.age =?1 order by x.name desc |
| Not | findByNameNot | ...where x.name <>?1 |
| In | findByAgeIn | ...where x.age in ?1 |
| NotIn | findByAgeNotIn | ...where x.age not in ?1 |
@Query注解
使用@Query注解在接口方法之上自定义执行SQL。
@Modifying
@Query(value = "update USER set USE_PHONE_NUM = :num WHERE USE_ID= :useId", nativeQuery = true)
void updateUsePhoneNum(@Param(value = "num") String num, @Param(value = "useId") int useId);
上面的更新语句必须加上@Modifying注解,其实在JpaRepository中并未定义更新的方法,所有的更新操作均需要我们自己来定义,一般采用上面的方式来完成。
/**
* 表示一个查询方法是修改查询,这会改变执行的方式。只在@Query注解标注的方法或者派生的方法上添加这个注解,而不能
* 用于默认实现的方法,因为这个注解会修改执行方式,而默认的方法已经绑定了底层的APi。
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Documented
public @interface Modifying {
boolean flushAutomatically() default false;
boolean clearAutomatically() default false;
}
JPQL(SQL拼接)
使用JPQL需要在持久层接口的实现列中完成,即UserRepositoryImpl,这个类是UserRepository的实现类,我们在其中定义JPQL来完成复杂的SQL查询,包括动态查询,连表查询等高级功能。
QBE(QueryByExampleExecutor)
使用QBE来进行持久层开发,需要用到两个接口类,Example和ExampleMatcher,开发方式如下:
List users = repository.findAll(Example.of(user));
或者配合ExampleMarcher使用:
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreCase();
List users = repository.findAll(Example.of(user, matcher));
以上逻辑一般位于service之中。其中user模型中保存着查询的条件值,null的字段不是条件,只有设置了值的字段才是条件。ExampleMatcher是用来自定义字段匹配模式的。
处理枚举
使用Spring-Data-Jpa时,针对枚举的处理有两种方式,对应于EnumType枚举的两个值:
public enum EnumType {
/** Persist enumerated type property or field as an integer. */
ORDINAL,
/** Persist enumerated type property or field as a string. */
STRING
}
其中ORDINAL表示的是默认的情况,这种情况下将会将枚举值在当前枚举定义的序号保存到数据库,这个需要是从0开始计算的,正对应枚举值定义的顺序。STRING表示将枚举的名称保存到数据库中。
前者用于保存序号,这对枚举的变更要求较多,我们不能随便删除枚举值,不能随意更改枚举值的位置,而且必须以0开头,而这一般又与我们定义的业务序号不一致,限制较多,一旦发生改变,极可能造成业务混乱;后者较为稳妥。
正常情况下,如果不在枚举字段上添加@Enumerated注解的话,默认就以ORDINAL模式存储,若要以STRING模式存储,请在枚举字段上添加如下注解:
@Enumerated(EnumType.STRING)
@Column(nullable=false) // 一般要加上非null约束
private UseState useState;
分页功能
Spring-Data-Jpa中实现分页使用到了Pageable接口,这个接口将作为一个参数参与查询。
Pageable有一个抽象实现类AbstractPageRequest,是Pageable的抽象实现,而这个抽象类有两个实现子类:PageRequest和QPageRequest,前者现已弃用,现在我们使用QPageRequest来定义分页参数,其有三个构造器:
public QPageRequest(int page, int size) {
this(page, size, QSort.unsorted());
}
public QPageRequest(int page, int size, OrderSpecifier<?>... orderSpecifiers) {
this(page, size, new QSort(orderSpecifiers));
}
public QPageRequest(int page, int size, QSort sort) {
super(page, size);
this.sort = sort;
}
在这里面我们可以看到一个QSort,这个QSort是专门用于与QPageRequest相配合使用的类,用于定义排序规则。默认情况下采用的是无排序的模式,即上面第一个构造器中的描述。
要构造一个QSort需要借助querydsl来完成,其中需要OrderSpecifier来完成。
这里有个简单的用老版本实现的分页查询:
public ResponseEntity<Page<User>> getUserPage(final int pageId) {
Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "useId"));
Page<User> users = repository.findAll(new PageRequest(pageId,2, sort));
return new ResponseEntity<>(users, HttpStatus.OK);
}
至于新版本的分页查询和排序涉及内容较多较复杂,稍后再看。
注意:分页首页页码为0
SpringBoot整合系列-整合JPA的更多相关文章
- SpringBoot整合系列--整合MyBatis-plus
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10125279.html SpringBoot整合MyBatis-plus 步骤 第一步: ...
- SpringBoot整合系列-整合H2
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9959855.html SpringBoot整合H2内存数据库 一般我们在测试的时候习惯于 ...
- SpringBoot整合系列-整合SpringMVC
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9984607.html SpringBoot整合Spring MVC 步骤 第一步:添加必 ...
- SpringBoot整合系列-整合MyBatis
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9971036.html SpringBoot整合Mybatis 步骤 第一步:添加必要的j ...
- SpringBoot整合系列-整合Swagger2
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9959844.html SpringBoot整合Swagger2 步骤 第一步:添加必要的 ...
- SpringBoot整合系列-PageHelper分页插件
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9971043.html SpringBoot整合MyBatis分页插件PageHelper ...
- SpringBoot系列-整合Mybatis(注解方式)
目录 一.常用注解说明 二.实战 三.测试 四.注意事项 上一篇文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介绍下Spring ...
- springboot整合spring Data JPA
今天敲代码,一连串的错误,我也是服气~果然,我们不是在出bug,就是在找bug的路上…… 今天完成的是springboot整合spring data JPA ,出了一连串的错,真是头大 java.sq ...
- SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂)
SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂) 当前环境说明: Windows10_64 Maven3.x JDK1.8 MySQL5.6 SpringTool ...
随机推荐
- 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习5
#include <iostream> using namespace std; const double N1=35000; const int N2=15000; const int ...
- :nth-child() 与 :nth-of-type(n)的区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 在虚拟机中安装Centos系统
1.首先下载VMware 2.然后可以去http://mirrors.aliyun.com下载映像ISO 3.打开VM,点击创建新的虚拟机 4.选择典型模式 5.稍后安装操作系统 6.选择你所要安装的 ...
- jdk12+tomcat9 配置
jdk12 没有了jre的配置 直接配置path就可以了 tomcat常规配置,只是启动的时候麻烦一点 需要重新写入jdk jre jvm 到server.bat文件 参考文章: https: ...
- Tensor索引操作
#Tensor索引操作 ''''' Tensor支持与numpy.ndarray类似的索引操作,语法上也类似 如无特殊说明,索引出来的结果与原tensor共享内存,即修改一个,另一个会跟着修改 ''' ...
- 使用Spring Aop自定义注解实现自动记录日志
百度加自己琢磨,以下亲测有效,所以写下来记录,也方便自己回顾浏览加深印象之类,有什么问题可以评论一起解决,不完整之处也请大佬指正,一起进步哈哈(1)首先配置文件: <!-- 声明自动为sprin ...
- [HACK] docker runtime 挂载宿主机目录
网上看到的很多所谓的挂载都是容器创建时期的挂载,而且参数都不清不楚,整理如下(--name别名自己加): docker run -v /src/path:/dest/path:rw ${IMAGE} ...
- Android第一次作业
Android第一次作业——天气预报界面 成果图: 思路: 运用RelativeLayout布局管理器来设计整体布局,在其中插入需要的图片和文本框,并设置其字体格式和背景.最后用HorizontalS ...
- 浅谈C++ STL
C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...
- 微信小程序----没有 DOM 对象,一切基于组件化 ---- mpvue
封装好用的 类库 和 组件,复用且灵活度高 抽取相同的部分放在函数内部(组件内部) 抽取不同的部分放在形参(组件 props 传参,或者插槽) new Promise 运行时 初始化实例对象的状态为 ...