【Java笔记+踩坑】Spring Data JPA

简介: 从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。

 导航:

【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析

目录

一、JPA介绍

二、准备

2.0 导入jpa依赖

2.1 用户表准备

2.2 实体类:@Entity,@Table,@Id,@Column

2.2.1 核心注解

2.2.2 代码示例:@Entity,@Table,@Id,@Column

2.2.3 主键策略:@GeneratedValue

2.3 增删改时填充用户名和日期

2.3.0 引导类开启审计:@EnableJpaAuditing

2.3.1 设置填充的用户名:AuditorAware

2.3.2 实体类填充注解:@EntityListeners(AuditingEntityListener.class)

二、DAO层

2.1 基本用法:继承JpaRepository<实体,ID类型>  

2.2 常用增删改查方法

2.2.1 查:find

2.2.2 增:save

2.2.3 改:save

2.2.4 删:delete

2.3 高级增删改查

2.3.1 分页查找

三、Service层

四、Controller层


一、JPA介绍

JPA即Java Persistence API,就是java持久化api,是SUN公司推出的一套基于ORM的规范。

ORM(Object-Relational Mapping):对象关系映射,简单来说为了不用JDBC那一套原始方法来操作数据库,ORM框架横空出世(mybatis、hibernate等等)。

二、准备

2.0 导入jpa依赖

<!-- Spring Boot JPA 依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

image.gif

2.1 用户表准备

CREATE TABLE `user` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(20) DEFAULT NULL COMMENT '姓名',    #DEFAULT是默认约束,DEFAULT NULL即默认是空
    `age` int(11) DEFAULT NULL COMMENT '年龄',
    `sex` varchar(1) DEFAULT NULL COMMENT '性别',
    `address` varchar(255) DEFAULT NULL COMMENT '地址',
    `phone` varchar(20) DEFAULT NULL COMMENT '电话',
    `create_time` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

image.gif

这里只有id是非空的,其他像姓名、年龄这些都可以是空。

+------------+---------------+------+-----+---------+-------+--------------+
|   列名     |     类型      | 空值 | 键  | 默认值  | 注释  |
+------------+---------------+------+-----+---------+-------+--------------+
|    id      |  bigint(20)   |  NO  | PRI |   AUTO_INCREMENT   | 供应商ID |
|   name     |  varchar(20)  |  YES |     |   NULL  | 姓名 |
|   age      |  int(11)      |  YES |     |   NULL  | 年龄 |
|   sex      |  varchar(1)   |  YES |     |   NULL  | 性别 |
|  address   |  varchar(255) |  YES |     |   NULL  | 地址 |
|   phone    |  varchar(20)  |  YES |     |   NULL  | 电话 |
| create_time|  varchar(20)  |  YES |     |   NULL  | 创建时间 |
+------------+---------------+------+-----+---------+-------+--------------+

image.gif

该表格展示了表的结构,包括列名、数据类型、是否允许空值、主键约束、默认值和注释。

2.2 实体类:@Entity,@Table,@Id,@Column

2.2.1 核心注解

注解 作用 常用属性
@Entity 指定当前类是实体类
@Table("表名") 指定实体类和表之间的对应关系 name:指定数据库表的名称
@EntityListeners 在实体类增删改的时候监听,为创建人/创建时间等基础字段赋值

value:指定监听类

@Id 指定当前字段是主键
@SequenceGenerator 指定数据库序列别名 sequenceName:数据库序列名
name:取的别名
@GeneratedValue 指定主键的生成方式 strategy :指定主键生成策略。默认AUTO自增,
generator:选择主键别名
@Column("表字段名") 指定实体类属性和数据库表之间的对应关系 name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
nserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的DDL
@CreatedBy 自动插入创建人,须搭配@EntityListeners
@CreatedDate 自动插入创建时间,须搭配@EntityListeners
@LastModifiedBy 自动修改更新人,须搭配@EntityListeners
@LastModifiedDate 自动修改更细时间,须搭配@EntityListeners
@Version 自动更新版本号
@JsonFormat 插入/修改/读取的时间转换成想要的格式 pattern:展示格式
timezone:国际时间

2.2.2 代码示例:@Entity,@Table,@Id,@Column

package com.example.entity;
import javax.persistence.*;
@Entity    // @Entity表明是一个实体类
@Table(name = "user")    //指定表名
public class User {
    @Id    //指定主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)    //指定生成策略
    private Long id;
    private String name;
    private Integer age;
    private String sex;
    private String address;
    private String phone;
    @Column(name = "create_time")    //指定列名
    private String createTime;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getCreateTime() {
        return createTime;
    }
    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
}

image.gif

2.2.3 主键策略:@GeneratedValue

  1. 自增长(Auto Increment)策略:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
  1. image.gif
  2. UUID策略:
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
private String id;
  1. image.gif

JPA本身不支持雪花算法。

2.3 增删改时填充用户名和日期

2.3.0 引导类开启审计:@EnableJpaAuditing

@EnableJpaAuditing

image.gif

2.3.1 设置填充的用户名:AuditorAware

@Configuration
public class UserAuditorAware implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // TODO: 根据实际情况取真实用户,这里固定返回"admin"
        return Optional.of("admin");
    }
}

image.gif

2.3.2 实体类填充注解:@EntityListeners(AuditingEntityListener.class)

@Data
@Entity
@Table(name = "JPA_USER")
@EntityListeners(AuditingEntityListener.class)    //当Entity增改时,监听信息。
public class JpaUser {
    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JPA_USER_S")
    @SequenceGenerator(sequenceName = "JPA_USER_S", name = "JPA_USER_S", allocationSize = 1)
    private Long id;
    @Column(name = "NAME")
    private String name;
    @Column(name = "OBJECT_VERSION" )
    @Version    //乐观锁。版本号字段会在每次更新实体时自动递增,并在更新时进行检查。如果两个并发的操作尝试更新同一个实体对象,只有其中一个操作会成功,而另一个操作会失败并抛出异常。
    private Long objectVersion;
    @Column(name = "CREATED_BY")
    @CreatedBy    //创建时,自动填充创建人。需要搭配上面的@EntityListeners
    private String createdBy;
    @Column(name = "CREATED_DATE")
    @CreatedDate    //创建时,自动填充创建时间。需要搭配上面的@EntityListeners
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createdDate;
    @Column(name = "LAST_UPDATED_BY" )
    @LastModifiedBy    //修改时,自动填充修改人。需要搭配上面的@EntityListeners
    private String lastUpdatedBy;
    @Column(name = "LAST_UPDATED_DATE" )
    @LastModifiedDate    //修改时,自动填充修改时间。需要搭配上面的@EntityListeners
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date lastUpdatedDate;
}

image.gif

二、DAO层

2.1 基本用法:继承JpaRepository<实体,ID类型>  

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

image.gif

2.2 常用增删改查方法

2.2.1 查:find

  • findById(id):根据ID查询单个实体对象。
Optional<User> user = userRepository.findById(1L);

image.gif

  • findAll():查询所有实体对象。
List<User> users = userRepository.findAll();

image.gif

  • findAllById(ids):根据ID列表查询多个实体对象。
List<User> users = userRepository.findAllById(Arrays.asList(1L, 2L, 3L));

image.gif

  • count():统计实体对象的总数。
long count = userRepository.count();

image.gif

2.2.2 增:save

save(entity):保存单个实体对象,根据实体对象的状态(新建或已存在)执行插入或更新操作。

saveAll(List<entitiy>):批量保存

User user = new User("John Doe", 25);
userRepository.save(user);

image.gif

2.2.3 改:save

save(entity):保存单个实体对象,根据实体对象的状态(新建或已存在)执行插入或更新操作。

User user = userRepository.findById(1L).orElse(null);
if (user != null) {
    user.setName("Updated Name");
    userRepository.save(user);
}

image.gif

2.2.4 删:delete

  • delete(entity):删除单个实体对象。
  • deleteById(id):根据ID删除单个实体对象。
  • deleteAll():删除所有实体对象。
  • deleteAll(List<entitiy>):批量删除多个实体对象。
User user = userRepository.findById(1L).orElse(null);
if (user != null) {
    userRepository.delete(user);
}
userRepository.deleteById(1L);
userRepository.deleteAll();
List<User> users = userRepository.findAllById(Arrays.asList(1L, 2L, 3L));
userRepository.deleteAll(users);

image.gif

2.3 高级增删改查

2.3.1 分页查找

public Page<User> findPage(Integer pageNum, Integer pageSize, String name) {
        // 构建分页查询条件
        Sort sort = new Sort(Sort.Direction.DESC, "create_time");
        Pageable pageRequest = PageRequest.of(pageNum - 1, pageSize, sort);
        return userRepository.findByNameLike(name, pageRequest);
    }

image.gif

三、Service层

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserRepository userRepository;
    public void save(User user) {
        String now = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        user.setCreateTime(now);
        userRepository.save(user);
    }
    public void delete(Long id) {
        userRepository.deleteById(id);
    }
    public User findById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
    public List<User> findAll() {
        return userRepository.findAll();
    }
    public Page<User> findPage(Integer pageNum, Integer pageSize, String name) {
        // 构建分页查询条件,建议写SQL分页
        Sort sort = new Sort(Sort.Direction.DESC, "create_time");
        Pageable pageRequest = PageRequest.of(pageNum - 1, pageSize, sort);
        return userRepository.findByNameLike(name, pageRequest);
    }
}

image.gif

四、Controller层

@RestController
@RequestMapping("/user")
public class JpaUserController {
    @Resource
    private JpaUserService jpaUserService;
    /**
     * 新增用户
     */
    @PostMapping("/add")
    public JpaUser addUser(@RequestBody JpaUser user){
        return jpaUserService.insertUser(user);
    }
    /**
     * 删除用户
     */
    @DeleteMapping("/delete/{id}")
    public void deleteUser(@PathVariable("id") Long id){
        jpaUserService.deleteUser(id);
    }
    /**
     * 修改用户
     */
    @PutMapping("/update")
    public JpaUser updateUser(@RequestBody JpaUser user){
        return jpaUserService.updateUser(user);
    }
    /**
     * 全查用户
     */
    @GetMapping("/all")
    public List<JpaUser> findAll(){
        return jpaUserService.findAllUser();
    }
    /**
     * id查用户
     */
    @GetMapping("/get/{id}")
    public JpaUser findbyId(@PathVariable("id") Long id){
        return jpaUserService.findUserById(id);
    }
}

image.gif


相关文章
|
28天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
28天前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、
【Java面试题汇总】Spring篇(2023版)
|
18天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
773 8
|
4天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
详细介绍实现Java Spring Boot FCM推送教程
19 0
Java初级笔记-第五章
第五章 面向对象的特点 5.1 继承 面向对象的重要特点之一就是继承。类的继承使得能够在已有的类的基础上构造新的类,新类除了具有被继承类的属性和方法外,还可以根据需要添加新的属性和方法。
1041 0
|
Java Windows 开发框架
Java初级笔记-第一章
第一章 Java概览 1.1 基本简介 Java是一种理想的面向对象的网络编程语言。 1991年,出现了Oak语言,旨在解决编程语言的选择和跨平台的问题。
1369 0
Java初级笔记-第二章
第二章 Java的基本数据类型、运算符及表达式 2.1 标识符 标识符是程序员对程序中的各个元素加以命名时使用的命名记号。
1200 0
|
存储 算法 Java
Java初级笔记-第三章
第三章 程序设计基础 3.1 流程图 3.1.1 什么是流程图: 流程图是通过箭头(流程线)相互连接的几何图形来表达程序运行的方法。
1408 0
Java初级笔记-第四章
第四章 类 4.1 类的概念 Java语言是一种纯面向对象的编程语言(OOP,你所有使用的内容,都是从类开始。
1268 0
|
14天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
34 2