概述
本来记了概述的,后来关机丢失了。那就不写了。进入正题。
整体
配置
首先引入pom文件。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
其后在SpringBoot的启动类之上,使用「@EnableJpaAuditing」注解。
使用
自动创建实体类表
这个功能说实话是我最喜欢的一个hhh,不用自己手动去设计数据库表了,当然,仅限于自己的小项目中使用啦~
在项目的yml加入以下配置。主要是「ddl-auto」这个属性,当我们设置为update之后就会通过实体类自动创建数据表。
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: false
而我们的实体类如何声明这个表的信息呢?在以下代码中,我们使用「@Entity」和「@Table(name = "sys_user")」两个注解。前者是声明这个是一个实体,然后数据库表的名称为「sys_user」。
@Entity
@Table(name = "sys_user")
public class SysUser
以下代码中可以看到,我们使用「@Id」注解来声明这个字段是我们数据表中的id,使用「@GenericGenerator」注解声明我们的主键生成策略是「uuid」。之后使用「@Column」进行配置字段相关信息,如「名称」和「长度」。
/**
* 用户ID
*/
@Id
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "id", length = 32)
private String id;
其他字段就大同小异了。
/**
* 用户名
*/
@Column(name = "user_name")
private String userName;
自动更新「update_time」与「update_time」
一般的,我们的数据表中都需要加入标题上这两种字段,我们不可能每次赋值的时候都手动的去添加吧。之前在MybatisPlus需要注解+拦截器去实现。而在JPA之中我们可以编写一个类,让别的类去继承它,从而实现这个功能。
如下代码中,主要使用「@EntityListeners(AuditingEntityListener.class)」注解进行拦截数据表的「更新」、「创建」等状态,然后进行重载数据。
然后在之后通过「@CreatedDate」和 「@LastModifiedDate」两个注解对其进行加载数据。
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
/**
* 创建时间
*/
@JsonIgnore
@CreatedDate
@Column(name = "create_time")
public Date createTime;
/**
* 修改时间
*/
@JsonIgnore
@LastModifiedDate
@Column(name = "update_time")
public Date updateTime;
}
如下类中便直接集成了这个类。
public class SysUser extends BaseEntity{
创建Mapper/自定义接口
在JPA之中,如同之前在使用MybatisPlus的时候一样,我们需要将其继承某个接口,然后它自动去实现这些。像下面代码中我们去继承了「JpaRepository<SysUser,Integer>」类(第二个参数代表它的ID类型),一些比较基础的SQL语句我们都不需要再自己编写。
并且,你也可以通过它的一些规则进行自己定义方法,并且JPA会自动给你去实现这个方法。如同下方代码「findByUsername」就代表它会自动实现一条根据「Username」这条字段为条件查询的SQL。很明显,它的生成策略在于:「findBy」 + 列名。
@Repository
public interface SysUserMapper extends JpaRepository<SysUser,Integer> {
SysUser findByUsername(String username);
}
相同的,它还提供了一些其他语法,如模糊查询 「findByUserNameLike」、and语句「findByUserNameAndPassword」等等。
最后我们采用「@Repository」去声明这个mapper。
分页
首先需要让mapper继承「PagingAndSortingRepository<实体类, 主键ID类型>」接口。
然后我们就可以直接通过「PageRequest」方法设置分页参数,再之后使用「findAll」方法并以这个分页对象为参数,就可以实现分页操作。
public Page<SysClassroom> list(int page, int size) {
PageRequest pageRequest = PageRequest.of(page - 1, size);
return sysClassroomMapper.findAll(pageRequest);
}
复杂SQL操作
在项目之中我遇到了一个场景——不仅需要分页操作,还需要一些条件!那么使用上述的分页方式就不行了。需要另寻办法。
我们的mapper需要继承于「JpaSpecificationExecutor」接口。
然后我们就需要在对应的service中构造对应的条件,我们需要去new一个名字叫为「Specification」的类,并且实现它的「toPredicate」方法。
Specification<SysChatMsg> specification1 = new Specification<SysChatMsg>() {
@Override
public Predicate toPredicate(Root<SysChatMsg> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
return null;
}
};
那么我们该怎么构建条件呢?我们需要借用类型为「CriteriaBuilder」的参数。用它来编写条件,最终再使用类型为「CriteriaQuery」的参数进行整体的SQL语句拼合。
如以下语句便构建了一个对名为「username」的列名进行了是否相同的对比。另外「criteriaBuilder」还有其他方法,常用的:排序、与、或、非等等。
Predicate a = criteriaBuilder
.equal(root.get("username").as(String.class), username);
Predicate b = criteriaBuilder
.equal(root.get("password").as(String.class), password);
最后再通过以下代码构建整个语句。
query.where(criteriaBuilder.or(a, b));
query.orderBy(criteriaBuilder.asc(root.get("createTime").as(Date.class)));
return query.getRestriction();
自此,条件便构建完毕了。
接下来我们可以直接通过mapper的「findAll」方法,分别传入条件和分页方法。
xxxMapper.findAll(specification,pageRequest);
本页的评论功能已关闭