阅读全文,约 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