最近是在项目中使用到了Spring Data JPA来减少大量重复SQL语句的编写,能够感觉到的确是使用起来很方便效率也比较高。Spring Data JPA 能够简化数据访问层的实现,让工程师不必去写一些CRUD的接口和实现。Spring Data JPA 自动提供CRUD的实现,能够部分解放工程师们的工作量。
通过本篇博客可以实现使用JPA进行CRUD
Spring Data JPA之自动创建数据库表
spring-data-jpa-crud demo
org.springframework.boot spring-boot-starter-parent 2.3.12.RELEASE org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java
server:port: 8099
spring:application:name: spring-data-jpadatasource:#mysq 驱动driver-class-name: com.mysql.cj.jdbc.Driver#连接数据库的url中配置ip和数据库名称以及时区url: jdbc:mysql://localhost:3306/spring_jpa?serverTimezone=Asia/Shanghai&characterEncoding=utf-8username: rootpassword: rootjpa:hibernate:#更新或者创建数据库表结构ddl-auto: update#控制台显示SQLshow-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的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
@MappedSuperclasspublic 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)//定义字段名和类型以及长度和备注,和是否允许为nullprivate 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 extends PagingAndSortingRepository, QueryByExampleExecutor {/** (non-Javadoc)* @see org.springframework.data.repository.CrudRepository#findAll()*/@OverrideList findAll();/** (non-Javadoc)* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)*/@OverrideList findAll(Sort sort);/** (non-Javadoc)* @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)*/@OverrideList findAllById(Iterable ids);/** (non-Javadoc)* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)*/@Override List saveAll(Iterable entities);/*** Flushes all pending changes to the database.*/void flush();/*** Saves an entity and flushes changes instantly.** @param entity* @return the saved entity*/ 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 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 List findAll(Example example);/** (non-Javadoc)* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)*/@Override List findAll(Example 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 {}
JpaRepository
由于JpaRepository
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 {/** @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 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数据访问接口@ResourceUserRepository userRepository;/** @version V1.0 * Title: insertUser* @author Wangwei * @description 插入用户信息* @createTime 2022/11/20 8:47* @param [user] * @return com.example.springdatajpa.entity.UserEntity**/@Overridepublic 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*/@Overridepublic 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**/@Overridepublic 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*/@Overridepublic List 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* */@Overridepublic UserEntity queryUserByPhoneNumber(UserEntity user) {return userRepository.findUserEntitiesByPhoneNumberAndIsDelete(user.getPhoneNumber(),0);}
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 {//注入业务接口@ResourceUserSerivce 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*/@GetMapping("/query")public List 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框架之间本质的区别还需要更加深入的学习和理解。