精通 Spring Boot 系列 09

简介: 精通 Spring Boot 系列 09

阅读全文,约 14 分钟

这是江帅帅的第011篇原创

案例2:关联查询和 @Query 查询

如果两个对象的查询,有关联关系,则可以在方法名中的添加下划线来标识。

我们就用 学生 和 班级 的关系,来给大家举个例子。

1)编辑 pom.xml 文件(与 CrudRepository 接口案例一样)
2)编辑 application.properties 文件(与 CrudRepository 接口案例一样)
3)创建 Student 和 Clazz 持久化类
// 学生
@Entity
@Table(name="tb_student")
public class Student implements Serializable{
 
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name ;
    private String address ;
    private int age ; 
    private char sex;
 
    // 学生与班级是多对一的关系,这里配置的是双向关联
    @ManyToOne(fetch=FetchType.LAZY, targetEntity=Clazz.class)
    @JoinColumn(name="clazzId", referencedColumnName="code")
 
    // 班级
    private Clazz clazz ;
 
    // 学生构造器
    public Student() {
    }
    public Student(String name, String address, int age, char sex,
            Clazz clazz) {
        super();
        this.name = name;
        this.address = address;
        this.age = age;
        this.sex = sex;
        this.clazz = clazz;
    }
 
    // getXxx 和 setXxx 方法
}
@Entity
@Table(name="tb_clazz")
public class Clazz implements Serializable{
 
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int code ;
    private String name ;
    // 班级与学生是一对多的关联
    @OneToMany(
               fetch=FetchType.LAZY,
               targetEntity=Student.class,
               mappedBy="clazz"
            )     
    private Set<Student> students = new HashSet<>();
 
    public Clazz() {
    }
    // 班级对象
    public Clazz(String name) {
        this.name = name;
    }
}
4)创建 ClazzRepository 和 StudentRepository 数据访问接口
public interface ClazzRepository extends JpaRepository<Clazz, Integer> {
}
public interface StudentRepository extends JpaRepository<Student, Integer> {
 
    /**
     * 根据班级名称查询这个班级下所有的学生信息
     * 相当于JPQL语句
     * select s from Student s where s.clazz.name = ?1
     */
    List<Student> findByClazz_name(String clazzName);
 
    /**
     * @Query 写法
     * 根据班级名称查询这个班级下所有的学生信息
     * ?1 此处使用的是参数的位置,代表的是第一个参数
     * 此写法与上面的方法实现的功能完全一致
     * */
    @Query("select s from Student s where s.clazz.name = ?1")
    List<Student> findStudentsByClazzName(String clazzName);
 
    /**
     * 使用 @Query 注解的形式,查询某个班级下所有学生的姓名和性别 
     */
    @Query("select new Map(s.name as name , s.sex as sex) "
            + "from Student s where s.clazz.name = ?1")
    List<Map<String, Object>> findNameAndSexByClazzName(String clazzName);
 
    /**
     *  使用 @Query 注解的形式,查询某个班级下某种性别的所有学生的姓名
     *  上面方法是用的是参数的位置来查询的,Spring Data JPA中还支持用
     *  名称来匹配查询使用格式 “:参数名称” 引用
     */
    @Query("select s.name from Student s "
            + "where s.clazz.name = :clazzName and s.sex = :sex ")
    List<String> findNameByClazzNameAndSex(@Param("clazzName")String clazzName , @Param("sex")char sex);
 
    /**
     *  使用 @Query 注解的形式,查询某个学生属于哪个班级
     */
    @Query("select c.name from Clazz c inner join c.students s "
            + "where s.name = ?1 ")
    String findClazzNameByStuName(String stuName);
 
    /**
     * 执行更新查询,使用 @Query与 @Modifying 可以执行更新操作
     */
    @Modifying
    @Query("delete from Student s where s.name = ?1")
    int deleteStuByStuName(String stuName);
}
5)创建 SchoolService 业务层类
@Service
public class SchoolService {
 
    // 注入数据访问层接口对象 
    @Resource
    private StudentRepository studentRepository;
    @Resource
    private ClazzRepository clazzRepository;
 
    @Transactional
    public void saveClazzAll(List<Clazz> clazzs) {
        clazzRepository.saveAll(clazzs);
    }
 
    @Transactional
    public void saveStudentAll(List<Student> students) {
        studentRepository.saveAll(students);
    }
 
    public List<Map<String, Object>> getStusByClazzName(String clazzName) {
 
        List<Student> students = studentRepository.findByClazz_name(clazzName);
        // List<Student> students = studentRepository.findStudentsByClazzName(clazzName);
 
        List<Map<String, Object>>  results = new ArrayList<>(); 
 
        // 遍历查询出的学生对象,提取姓名,年龄,性别信息
        for(Student student:students){
            Map<String , Object> stu = new HashMap<>(); 
            stu.put("name", student.getName());
            stu.put("age", student.getAge());
            stu.put("sex", student.getSex());
            results.add(stu);
        }
        return results;
    }
 
    public List<Map<String, Object>> findNameAndSexByClazzName(String clazzName) {
        return studentRepository.findNameAndSexByClazzName(clazzName);
    }
 
    public List<String> findNameByClazzNameAndSex(
            String clazzName, char sex) {
        return studentRepository.findNameByClazzNameAndSex(clazzName, sex);
    }
 
    public String findClazzNameByStuName(String stuName) {
        return studentRepository.findClazzNameByStuName(stuName);
    }
 
    @Transactional
    public int deleteStuByStuName(String stuName) {
        return studentRepository.deleteStuByStuName(stuName);
    }
}
6)创建 StudentController 控制器类
@RestController
@RequestMapping("/student")
public class StudentController {
 
    @Resource
    private SchoolService schoolService;
    @RequestMapping("/save")
    public String save() {
 
        Clazz clazz1 = new Clazz("架构师 001 班");
        Clazz clazz2 = new Clazz("架构师 002 班");
 
        // 保存班级对象数据
        List<Clazz> clazzs = new ArrayList<>();
        clazzs.add(clazz1);
        clazzs.add(clazz2);
        schoolService.saveClazzAll(clazzs);
 
        Student s1 = new Student("小黄","广州",18,'男',clazz1);
        Student s2 = new Student("小红","北京",17,'女',clazz1);
        Student s3 = new Student("小绿","成都",15,'男',clazz2);
 
        List<Student> students = new ArrayList<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
 
        schoolService.saveStudentAll(students);
 
        return "保存学生对象成功";
    }
 
    /**
     * 查询某个班级下所有的学生姓名,年龄,性别
     */
    @RequestMapping("/getClazzStus")
    public List<Map<String, Object>> getClazzStus(String clazzName){
        return schoolService.getStusByClazzName(clazzName);
    } 
 
    /**
     * 查询某个班级下所有的学生姓名,性别
     */
    @RequestMapping("/findNameAndSexByClazzName")
    public List<Map<String, Object>> findNameAndSexByClazzName(String clazzName){
        return schoolService.findNameAndSexByClazzName(clazzName);
    } 
 
    /**
     * 查询某个班级下某种性别的所有学生的姓名
     */
    @RequestMapping("/findNameByClazzNameAndSex")
    public List<String> findNameByClazzNameAndSex(String clazzName ,Character sex){
        return schoolService.findNameByClazzNameAndSex(clazzName ,sex);
    } 
 
    /**
     * 查询某个学生属于哪个班级
     */
    @RequestMapping("/findClazzNameByStuName")
    public String findClazzNameByStuName(String stuName){
        return schoolService.findClazzNameByStuName(stuName);
    } 
 
    /**
     * 删除某个学生对象
     */
    @RequestMapping("/deleteStuByStuName")
    public String deleteStuByStuName(String stuName){
        return "删除数据:"+schoolService.deleteStuByStuName(stuName);
    } 
}
7)测试

http://localhost:8080/student/save

目录
相关文章
|
12天前
|
存储 安全 Java
精通 Spring Boot 系列 14
精通 Spring Boot 系列 14
11 0
|
12天前
|
存储 安全 Java
精通 Spring Boot 系列 15
精通 Spring Boot 系列 15
24 0
|
12天前
|
Java Spring
精通 Spring Boot 系列 08
精通 Spring Boot 系列 08
22 0
|
12天前
|
Java 数据库连接 数据库
精通 Spring Boot 系列 13
精通 Spring Boot 系列 13
23 0
|
12天前
|
前端开发 Java 文件存储
精通 Spring Boot 系列 06
精通 Spring Boot 系列 06
28 0
|
12天前
|
Java 数据库 Spring
精通 Spring Boot 系列 12
精通 Spring Boot 系列 12
24 0
|
12天前
|
Java 关系型数据库 数据库连接
精通 Spring Boot 系列 07
精通 Spring Boot 系列 07
18 0
|
12天前
|
Java Spring
精通 Spring Boot 系列 10
精通 Spring Boot 系列 10
23 0
|
7月前
|
Cloud Native Java Go
《Spring Boot前世今生》
《Spring Boot前世今生》
26 0
|
XML 监控 Java
初学Spring Boot 必须要知道的事
Spring Boot简介 Spring Boot 核心功能 Spring Boot的优缺点 SpringBoot 常用注解和原理
138 0