SpringBoot中使用JPA进行一对多查询

一、JPA介绍

Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。

值得注意的是,Jpa是在充分吸收了现有 Hibernate,TopLink,JDO 等 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,Jpa 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3. 0的开发团队。

注意:Jpa 是一套规范,不是一套产品,那么像 Hibernate,TopLink,JDO 他们是一套产品,如果说这些产品实现了这个 Jpa 规范,那么我们就可以叫他们为 Jpa 的实现产品。

Spring Boot Jpa 是 Spring 基于 ORM 框架、Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data Jpa 可以极大提高开发效率!

Spring Boot Jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现

二、项目搭建

2.1添加Spring Data JPA依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.5.0</version>
</dependency>

2.2 添加数据库驱动依赖

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

2.3添加配置文件 application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    tomcat:
      max-active: 20
      max-idle: 8
      initial-size: 10
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database: mysql
    open-in-view: true #解决no-Session的问题
    properties:
      hibernate:
        enable_lazy_load_no_trans: true

三、编写代码

3.1编写实体类

JPA中实体类注解介绍:@Entity为指定改类为表实体类,name属性对应为数据库表名,@Id为指定该字段为数据库主键,@GeneratedValue为指定主键的增长策略,@GenericGenerator为自定义主键的增长策略,当我们需要一对多操作时只需要在该实体类引用需要操作的实体类,并加上@OneToMany(mappedBy = “department”, cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)注解,其中@OneToMany表名是一对多操作,mappedBy是映射的实体类名,cascade 为级联,当我们对该字段操作变化时,依赖他的字段都会随着发生变化,fetch 为加载时机(LAZY为懒加载,EAGER为及时加载)。

3.1.1 部门表(Department)

package com.ls.entity;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.util.Set;
/*
 * @Author:Alan
 * @Date:2021/6/8 16:53
 * @Description 部门实体类
 * @param: null
 * @return
 */
@Entity(name = "tb_dept")
//@Data
@Getter
@Setter
public class Department {
    @Id
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @GeneratedValue(generator = "idGenerator")
    private String id;
    private String deptName;

    //希望:查询一个部门的所有信息的信息,同时查询数这个部门中所有员工的所有信息。
    /*
   cascade:级联(一个犯法,满门cz)
            CascadeType.MERGE级联更新:若User属性修改了那么中间表保存时同时修改items里的对象。对应EntityManager的merge方法 (较常用  )

            CascadeType.PERSIST级联保存:对user对象保存时也对role里的对象也会保存。对应EntityManager的presist方法

            CascadeType.REFRESH级联刷新:获取user对象也同时也重新获取最新的role时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据

            CascadeType.REMOVE级联删除:对users对象删除也对中间表role里的对象也会删除。对应EntityManager的remove方法

            CascadeType.ALL包含所有;
    fetch:抓取策略
            fetch.lazy  :懒加载    获取Department对象信息时,不会马上去获取该部门对应的所有员工信息
            当我们通过department.getEmployees*()是才会去获取该用户的所有角色的所有信息。
            fetch.EAGER  立即加载   获取user对象信息时,会立即获取该用户所对用的所有角色的所有信息。

    mappedBy:必须与员工的Department的属性名一致,否则查询不出员工信息
     */
    //jpa  could not initialize proxy - no Session
    @OneToMany(mappedBy = "department", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
    //@OneToMany(mappedBy = "department",cascade = {CascadeType.ALL},fetch = FetchType.EAGER)
    private Set<Employee> employees;

    @Override
    public String toString() {
        return "Department{" +
                "id='" + id + ''' +
                ", deptName='" + deptName + ''' +
                '}';
    }

3.1.2 员工表(Employee)

每个员工只属于一个部门,而一个部门可以有多个员工,所有在员工表中定义部门实体类时需要加上 @ManyToOne(targetEntity = Department.class,fetch = FetchType.EAGER),ManyToOne为多对一注解,targetEntity 为目标的实体类名,fetch 为加载时机, @JoinColumn(name=“dept_id”,referencedColumnName = “id”),JoinColumn的name属性为目标连接的字段名,referencedColumnName 为自己所引用的字段名。

package com.ls.entity;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
/**
 * @ClassName Employee
 * @Description 员工实体类
 * @Author Alan
 * @Date 2021/6/8 16:53
 * @Version 1.0
 **/
@Entity
@Table(name="tb_emp")
//@Data
@Getter
@Setter
public class Employee {
    @Id
    //主键字符串,通过程序自动生产主键值
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @GeneratedValue(generator = "idGenerator")
    private String id;
    private String empName;
    private String empJob;
    //只查找部门的id
    //private String deptId;
    //希望:查询这个员工所有的信息的时候,同时也查出这个员工的部门的所有信息
    /*cascade:级联(一个犯法,满门cz)
            CascadeType.MERGE级联更新:若User属性修改了那么中间表保存时同时修改items里的对象。对应EntityManager的merge方法 (较常用  )

            CascadeType.PERSIST级联保存:对user对象保存时也对role里的对象也会保存。对应EntityManager的presist方法

            CascadeType.REFRESH级联刷新:获取user对象也同时也重新获取最新的role时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据

            CascadeType.REMOVE级联删除:对users对象删除也对中间表role里的对象也会删除。对应EntityManager的remove方法

            CascadeType.ALL包含所有;
    fetch:抓取策略
            fetch.lazy  :懒加载    获取user对象信息时,不会马上去获取该用户对应的所有角色信息
            当我们通过user.getRoles是才会去获取该用户的所有角色的所有信息。
            fetch.EAGER  立即加载   获取user对象信息时,会立即获取该用户所对用的所有角色的所有信息。
    */
    @ManyToOne(targetEntity = Department.class,fetch = FetchType.EAGER)
    @JoinColumn(name="dept_id",referencedColumnName = "id")
    private Department department;

    @Override
    public String toString() {
        return "Employee{" +
                "id='" + id + ''' +
                ", empName='" + empName + ''' +
                ", empJob='" + empJob + ''' +
                '}';
    }
}

3.2 编写Repository接口

Repository接口类似MybBatis的mapper接口,它通过实现JpaRepository<实体类,主键类型>,它内部实现了基本的增(save)删(deleteById)查(findAll)改(save(需要修改的id))方法。

3.2.1 部门接口(DepartmentRepository)

package com.ls.repository;

import com.ls.entity.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/*
 * @Author:Alan
 * @Date:2021/6/8 23:08
 * @Description 部门接口
 * @param: null
 * @return
*/
@Repository
public interface DepartmentRepository extends JpaRepository<Department,String> {
//    通过部门名称查询
    Department findByDeptName(String deptName);
}

3.2.2 员工接口(EmployeeRepository)

package com.ls.repository;

import com.ls.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/*
 * @Author:Alan
 * @Date:2021/6/8 16:54
 * @Description 员工接口
 * @param: null
 * @return
*/
@Repository
public interface EmployeeRepository extends JpaRepository<Employee,String> {
}

四、编写测试类

 //    查询部门表下有多少员工
    @SpringBootTest
public class UserRoleTest {
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private EmployeeRepository employeeRepository;
    @Autowired
    @Test
    void Test01() {
        Department department = departmentRepository.findByDeptName("开发部");
        System.out.println(department);
        Set<Employee> employeeSet = department.getEmployees();
        employeeSet.forEach(System.out::println);
    }
 }

最后可以看到查询情况如下:
在这里插入图片描述
在这里插入图片描述
以上就是JPA的简单一对多使用和介绍。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用SpringBootJPA进行多对多查询时,可以按照以下步骤进行操作: 1. 首先,要确保项目已经引入了所需的依赖,包括spring-boot-starter-data-jpa和相关数据库的依赖(例如h2数据库)。 2. 然后,在实体类定义多对多的关系。假设我们有两个实体类:User和Role,它们之间是多对多的关系。可以使用@ManyToMany注解来实现这种关系。在User实体类使用@ManyToMany注解将User与Role关联起来,而在Role实体类使用@ManyToMany注解将Role与User关联起来。 3. 接下来,需要在数据库创建适当的表来存储多对多的关系。使用JPA的自动建表功能,可以根据实体类的定义自动生成相应的表结构。 4. 对于多对多查询,可以使用JPA提供的方法来进行操作。例如,可以在UserRepository定义一个方法,使用@Query注解来编写自定义的查询语句,从而实现多对多的查询操作。 5. 最后,可以在Controller层调用相应的Service方法,将查询结果返回给前端。 综上所述,使用SpringBootJPA进行多对多查询的步骤包括引入所需的依赖、定义实体类的多对多关系、创建数据库表、编写查询方法和调用查询方法。通过这些步骤,可以实现多对多查询的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot JPA实现查询多值](https://download.csdn.net/download/weixin_38599430/12756496)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [spring data jpa关联查询(一对一、一对多、多对多)](https://blog.csdn.net/WGH100817/article/details/101720340)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值