Spring boot整合JPA进行CRUD
- 前言
- 系列博客
- 本博客的实现demo
- 环境配置
- 1.POM依赖
- 2.application.yml文件
- 完整的项目结构
- 代码实现
- 实体类
- 启动类
- 创建数据访问层
- 使用Spring Data JPA 创建带条件的CRUD
- 编写业务层
- 创建UserController类
- 运行测试
- 插入用户数据
- 删除用户数据
- 修改数据
- 查询数据
- 根据手机号查询
- 总结
- 如果博主的文章对您有所帮助,可以评论、点赞、收藏,支持一下博主!!!
前言
最近是在项目中使用到了Spring Data JPA来减少大量重复SQL语句的编写,能够感觉到的确是使用起来很方便效率也比较高。Spring Data JPA 能够简化数据访问层的实现,让工程师不必去写一些CRUD的接口和实现。Spring Data JPA 自动提供CRUD的实现,能够部分解放工程师们的工作量。
通过本篇博客可以实现使用JPA进行CRUD
系列博客
Spring Data JPA之自动创建数据库表
本博客的实现demo
spring-data-jpa-crud demo
环境配置
- 创建一个Maven项目并引入依赖
1.POM依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!--spring boot 启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--spring mvc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring boot 开发工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--spring boot 测试工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--jpa 启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql连接器-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2.application.yml文件
server:
port: 8099
spring:
application:
name: spring-data-jpa
datasource:
#mysq 驱动
driver-class-name: com.mysql.cj.jdbc.Driver
#连接数据库的url中配置ip和数据库名称以及时区
url: jdbc:mysql://localhost:3306/spring_jpa?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
username: root
password: root
jpa:
hibernate:
#更新或者创建数据库表结构
ddl-auto: update
#控制台显示SQL
show-sql: true
完整的项目结构
比较典型的MVC项目结构,在JPA里面将熟悉的dao层数据操作层用repository来命名
代码实现
实体类
目前有一个实体类,一个基础类(用于抽象出一些公共的字段)
基础类BaseEntity
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.util.Date;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : BaseEntity
* @description : [基础类]
* @createTime : [2022/11/18 15:32]
* @updateUser : [WangWei]
* @updateTime : [2022/11/18 15:32]
* @updateRemark : [描述说明本次修改内容]
*/
//@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
@MappedSuperclass
public class BaseEntity {
//定义字段以及字段的类型和长度和是否允许为null
@Column(name = "create_by",columnDefinition = "varchar(32) COMMENT '创建人'",nullable = false)
private String createdBy;
@Column(name = "created_id",columnDefinition = "varchar(32) COMMENT '创建人id'",nullable = false)
private Long createdId;
@Column(name = "create_time",nullable = false,columnDefinition = "DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Column(name = "updated_by",columnDefinition = "varchar(32) COMMENT '更新人'")
private String updateBy;
@Column(name = "updated_id",columnDefinition = "varchar(32) COMMENT '更新人id'")
private Long updateId;
定义字段以及字段的类型并默认为当前时间,并当进行修改的时候更新时间为当前实现
@Column(name = "update_time",columnDefinition = "DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@Column(name = "is_delete",columnDefinition = "tinyint(1) COMMENT '是否删除(0/1 未删除/删除)'")
private int isDelete=0;
@Column(name = "remark",columnDefinition = "varchar(64) COMMENT '备注'")
private String remark;
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Long getCreatedId() {
return createdId;
}
public void setCreatedId(Long createdId) {
this.createdId = createdId;
}
public Long getUpdateId() {
return updateId;
}
public void setUpdateId(Long updateId) {
this.updateId = updateId;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public int getIsDelete() {
return isDelete;
}
public void setIsDelete(int isDelete) {
this.isDelete = isDelete;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
实体类UserEntity
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserEntity
* @description : [用户实体类]
* @createTime : [2022/11/18 14:57]
* @updateUser : [WangWei]
* @updateTime : [2022/11/18 14:57]
* @updateRemark : [描述说明本次修改内容]
*/
@Entity //声明类为实体类
@Table(name="jpa_user")//对应创建之后的表名
public class UserEntity extends BaseEntity{
@Id
@Column(name = "user_code",columnDefinition = "bigint(20) COMMENT '学号'",nullable = false)//定义字段名和类型以及长度和备注,和是否允许为null
private Long id;
@Column(name="user_Name",nullable = false,columnDefinition = "varchar(32) COMMENT '用户名'")
private String userName;
@Column(name="pass_word",nullable = false,columnDefinition = "varchar(32) COMMENT '密码'")
private String password;
@Column(name="phone_Number",nullable = false,columnDefinition = "varchar(16) COMMENT '手机号'")
private String phoneNumber;
@Column(name="sex",columnDefinition = "varchar(2) COMMENT '性别'")
private String sex;
@Column(name="birthday",nullable = false,columnDefinition = "datetime COMMENT '生日日期'")
@DateTimeFormat(pattern = "yyyy-MM-dd ")
private Date birthday;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
启动类
此时已经可以直接运行启动类,启动程序时候在数据库中会直接生成相应的表。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataJpaApplication.class, args);
}
}
可以在mysql中查看,或者在Navicat上查看到已经创建的表
创建数据访问层
在repository中创建UserRepository接口继承JpaRepository接口,JpaRepository接口提供了一些的增删改查的方法。
JpaRepository接口
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findAll()
*/
@Override
List<T> findAll();
/*
* (non-Javadoc)
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
@Override
List<T> findAll(Sort sort);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
*/
@Override
List<T> findAllById(Iterable<ID> ids);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
*/
@Override
<S extends T> List<S> saveAll(Iterable<S> entities);
/**
* Flushes all pending changes to the database.
*/
void flush();
/**
* Saves an entity and flushes changes instantly.
*
* @param entity
* @return the saved entity
*/
<S extends T> S saveAndFlush(S entity);
/**
* Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
* the {@link javax.persistence.EntityManager} after the call.
*
* @param entities
*/
void deleteInBatch(Iterable<T> entities);
/**
* Deletes all entities in a batch call.
*/
void deleteAllInBatch();
/**
* Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
* implemented this is very likely to always return an instance and throw an
* {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
* immediately.
*
* @param id must not be {@literal null}.
* @return a reference to the entity with the given identifier.
* @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
*/
T getOne(ID id);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
*/
@Override
<S extends T> List<S> findAll(Example<S> example);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
*/
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
UserRepository接口
import com.example.springdatajpa.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserRepository
* @description : [User数据访问接口]
* @createTime : [2022/11/19 19:15]
* @updateUser : [WangWei]
* @updateTime : [2022/11/19 19:15]
* @updateRemark : [描述说明本次修改内容]
*/
public interface UserRepository extends JpaRepository<UserEntity,Long> {
}
JpaRepository<T, ID>T表示实体的类型,ID表示实体类中ID的类型。
使用Spring Data JPA 创建带条件的CRUD
由于JpaRepository<T, ID>接口只定义了一些较为简单的CRUD,但是对于一些带条件的CRUDJpaRepository并没有给出,但是我们可以在继承JpaRepository<T, ID>接口的接口中创建相应的方法。
import com.example.springdatajpa.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserRepository
* @description : [描述说明该类的功能]
* @createTime : [2022/11/19 19:15]
* @updateUser : [WangWei]
* @updateTime : [2022/11/19 19:15]
* @updateRemark : [描述说明本次修改内容]
*/
public interface UserRepository extends JpaRepository<UserEntity,Long> {
/*
* @version V1.0
* Title: findUserEntitiesByPhoneNumberAndIsDelete
* @author Wangwei
* @description 根据手机号查询
* @createTime 2022/11/20 10:00
* @param [phoneNumber, isDelete]
* @return com.example.springdatajpa.entity.UserEntity
*/
UserEntity findUserEntitiesByPhoneNumberAndIsDelete(String phoneNumber,int isDelete);
}
创建相应的方法,先定义方法的返回值,在定义操作类型(find,delete,search)+By+条件
如果有需要可以参考Spring Data Jpa官网上Spring Data Jpa
编写业务层
UserSerivce接口
import com.example.springdatajpa.entity.UserEntity;
import java.util.List;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserSerivce
* @description : [User业务层接口]
* @createTime : [2022/11/19 20:27]
* @updateUser : [WangWei]
* @updateTime : [2022/11/19 20:27]
* @updateRemark : [描述说明本次修改内容]
*/
public interface UserSerivce {
//新增用户
UserEntity insertUser(UserEntity user);
//删除用户
void deleteUser(Long id);
//修改用户信息
UserEntity updateUser(UserEntity user);
//查询所有用户
List<UserEntity> queryUser();
//根据手机号查询用户信息
UserEntity queryUserByPhoneNumber(UserEntity user);
}
UserServiceImpl实现类
import com.example.springdatajpa.entity.UserEntity;
import com.example.springdatajpa.repository.UserRepository;
import com.example.springdatajpa.service.UserSerivce;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserServiceImpl
* @description : [User业务实现类]
* @createTime : [2022/11/19 20:33]
* @updateUser : [WangWei]
* @updateTime : [2022/11/19 20:33]
* @updateRemark : [描述说明本次修改内容]
*/
@Service
public class UserServiceImpl implements UserSerivce {
//User数据访问接口
@Resource
UserRepository userRepository;
/*
* @version V1.0
* Title: insertUser
* @author Wangwei
* @description 插入用户信息
* @createTime 2022/11/20 8:47
* @param [user]
* @return com.example.springdatajpa.entity.UserEntity
**/
@Override
public UserEntity insertUser(UserEntity user) {
return userRepository.save(user);
}
/*
* @version V1.0
* Title: deleteUser
* @author Wangwei
* @description 根据id删除用户信息
* @createTime 2022/11/20 8:48
* @param [id]
* @return void
*/
@Override
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
/*
* @version V1.0
* Title: updateUser
* @author Wangwei
* @description 修改用户信息,save方法是如果存在这条数据则进行修改否则进行新增
* @createTime 2022/11/20 8:49
* @param [user]
* @return com.example.springdatajpa.entity.UserEntity
**/
@Override
public UserEntity updateUser(UserEntity user) {
return userRepository.save(user);
}
/*
* @version V1.0
* Title: queryUser
* @author Wangwei
* @description 查询所有用户
* @createTime 2022/11/20 8:50
* @param []
* @return java.util.List<com.example.springdatajpa.entity.UserEntity>
*/
@Override
public List<UserEntity> queryUser() {
return userRepository.findAll();
}
/*
* @version V1.0
* Title: queryUserByPhoneNumber
* @author Wangwei
* @description 通过手机号查询用户信息
* @createTime 2022/11/20 8:50
* @param [user]
* @return com.example.springdatajpa.entity.UserEntity
* */
@Override
public UserEntity queryUserByPhoneNumber(UserEntity user) {
return userRepository.findUserEntitiesByPhoneNumberAndIsDelete(user.getPhoneNumber(),0);
}
创建UserController类
import com.example.springdatajpa.entity.UserEntity;
import com.example.springdatajpa.service.UserSerivce;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : UserController
* @description : [User控制层类]
* @createTime : [2022/11/19 20:40]
* @updateUser : [WangWei]
* @updateTime : [2022/11/19 20:40]
* @updateRemark : [描述说明本次修改内容]
*/
@RestController
@RequestMapping("/user")
public class UserController {
//注入业务接口
@Resource
UserSerivce userSerivce;
/*
* @version V1.0
* Title: insertUser
* @author Wangwei
* @description 新增用户
* @createTime 2022/11/20 8:54
* @param [user]
* @return UserEntity
*/
@PostMapping("/insert")
public UserEntity insertUser(@RequestBody UserEntity user){
return userSerivce.insertUser(user);
}
/*
* @version V1.0
* Title: deleteUser
* @author Wangwei
* @description 通过id删除用户
* @createTime 2022/11/20 8:56
* @param [id]
* @return void
*/
@DeleteMapping("delete/{id}")
public void deleteUser(@PathVariable("id") Long id){
userSerivce.deleteUser(id);
}
/*
* @version V1.0
* Title: updateUser
* @author Wangwei
* @description:修改用户信息
* @createTime 2022/11/20 8:57
* @param [user]
* @return com.example.springdatajpa.entity.UserEntity
* */
@PutMapping("/update")
public UserEntity updateUser(@RequestBody UserEntity user){
return userSerivce.updateUser(user);
}
/*
* @version V1.0
* Title: queryUser
* @author Wangwei
* @description 查询所有用户信息
* @createTime 2022/11/20 9:25
* @param []
* @return java.util.List<com.example.springdatajpa.entity.UserEntity>
*/
@GetMapping("/query")
public List<UserEntity> queryUser(){
return userSerivce.queryUser();
}
@GetMapping("/query/{phoneNumber}")
public UserEntity queryUserByPhoneNumber(@PathVariable("phoneNumber") String phoneNumber){
return userSerivce.queryUserByPhoneNumber(phoneNumber);
}
}
运行测试
选择使用postman进行调用接口测试
插入用户数据
{
"createdBy": "wangwei",
"createdId": 3,
"createTime": "2022-11-20T02:20:08.000+00:00",
"updateBy": "wangwei",
"updateId": 3,
"updateTime": "2022-11-20T02:20:08.000+00:00",
"isDelete": 0,
"remark": null,
"id": 1,
"userName": "wangwei",
"password": "003",
"phoneNumber": "110",
"sex": "男",
"birthday": "2022-11-20T02:19:40.000+00:00"
}
删除用户数据
修改数据
查询数据
根据手机号查询
总结
目前只是对Spring Data JPA的基础运用,对于JPA与mybatis这一类的ORM框架之间本质的区别还需要更加深入的学习和理解。