精通 Spring Boot 系列文(9)
閱讀全文,約 30?分鐘

案例2:關(guān)聯(lián)查詢和 @Query 查詢
如果兩個(gè)對(duì)象的查詢,有關(guān)聯(lián)關(guān)系,則可以在方法名中的添加下劃線來標(biāo)識(shí)。
我們就用 學(xué)生?和 班級(jí) 的關(guān)系,來給大家舉個(gè)例子。
1)編輯 pom.xml 文件(與 CrudRepository 接口案例一樣)
2)編輯 application.properties 文件(與 CrudRepository 接口案例一樣)
3)創(chuàng)建 Student 和 Clazz 持久化類
//?學(xué)生
@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;
????//?學(xué)生與班級(jí)是多對(duì)一的關(guān)系,這里配置的是雙向關(guān)聯(lián)
????@ManyToOne(fetch=FetchType.LAZY,?targetEntity=Clazz.class)
????@JoinColumn(name="clazzId",?referencedColumnName="code")
????//?班級(jí)
????private?Clazz?clazz?;
????//?學(xué)生構(gòu)造器
????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?;
????//?班級(jí)與學(xué)生是一對(duì)多的關(guān)聯(lián)
????@OneToMany(
???????????????fetch=FetchType.LAZY,
???????????????targetEntity=Student.class,
???????????????mappedBy="clazz"
????????????)?????
????private?Set?students?=?new?HashSet<>();
????public?Clazz()?{
????}
????//?班級(jí)對(duì)象
????public?Clazz(String?name)?{
????????this.name?=?name;
????}
}
4)創(chuàng)建 ClazzRepository 和 StudentRepository 數(shù)據(jù)訪問接口
public?interface?ClazzRepository?extends?JpaRepository<Clazz,?Integer>?{
}
public?interface?StudentRepository?extends?JpaRepository<Student,?Integer>?{
????/**
?????*?根據(jù)班級(jí)名稱查詢這個(gè)班級(jí)下所有的學(xué)生信息
?????*?相當(dāng)于JPQL語句
?????*?select?s?from?Student?s?where?s.clazz.name?=??1
?????*/
????List?findByClazz_name(String?clazzName) ;
????/**
?????*?@Query?寫法
?????*?根據(jù)班級(jí)名稱查詢這個(gè)班級(jí)下所有的學(xué)生信息
?????*??1?此處使用的是參數(shù)的位置,代表的是第一個(gè)參數(shù)
?????*?此寫法與上面的方法實(shí)現(xiàn)的功能完全一致
?????*?*/
????@Query("select?s?from?Student?s?where?s.clazz.name?=??1")
????List?findStudentsByClazzName(String?clazzName) ;
????/**
?????*?使用?@Query?注解的形式,查詢某個(gè)班級(jí)下所有學(xué)生的姓名和性別?
?????*/
????@Query("select?new?Map(s.name?as?name?,?s.sex?as?sex)?"
????????????+?"from?Student?s?where?s.clazz.name?=??1")
????List5)創(chuàng)建 SchoolService 業(yè)務(wù)層類
@Service
public?class?SchoolService?{
????//?注入數(shù)據(jù)訪問層接口對(duì)象?
????@Resource
????private?StudentRepository?studentRepository;
????@Resource
????private?ClazzRepository?clazzRepository;
????@Transactional
????public?void?saveClazzAll(List?clazzs) ?{
????????clazzRepository.saveAll(clazzs);
????}
????@Transactional
????public?void?saveStudentAll(List?students) ?{
????????studentRepository.saveAll(students);
????}
????public?List6)創(chuàng)建 StudentController 控制器類
@RestController
@RequestMapping("/student")
public?class?StudentController?{
????@Resource
????private?SchoolService?schoolService;
????@RequestMapping("/save")
????public?String?save()?{
????????Clazz?clazz1?=?new?Clazz("架構(gòu)師?001?班");
????????Clazz?clazz2?=?new?Clazz("架構(gòu)師?002?班");
????????//?保存班級(jí)對(duì)象數(shù)據(jù)
????????List?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?students?=?new?ArrayList<>();
????????students.add(s1);
????????students.add(s2);
????????students.add(s3);
????????schoolService.saveStudentAll(students);
????????return?"保存學(xué)生對(duì)象成功";
????}
????/**
?????*?查詢某個(gè)班級(jí)下所有的學(xué)生姓名,年齡,性別
?????*/
????@RequestMapping("/getClazzStus")
????public?List>?getClazzStus(String?clazzName){
????????return?schoolService.getStusByClazzName(clazzName);
????}?
????/**
?????*?查詢某個(gè)班級(jí)下所有的學(xué)生姓名,性別
?????*/
????@RequestMapping("/findNameAndSexByClazzName")
????public?List>?findNameAndSexByClazzName(String?clazzName){
????????return?schoolService.findNameAndSexByClazzName(clazzName);
????}?
????/**
?????*?查詢某個(gè)班級(jí)下某種性別的所有學(xué)生的姓名
?????*/
????@RequestMapping("/findNameByClazzNameAndSex")
????public?List?findNameByClazzNameAndSex(String?clazzName?,Character?sex) {
????????return?schoolService.findNameByClazzNameAndSex(clazzName?,sex);
????}?
????/**
?????*?查詢某個(gè)學(xué)生屬于哪個(gè)班級(jí)
?????*/
????@RequestMapping("/findClazzNameByStuName")
????public?String?findClazzNameByStuName(String?stuName){
????????return?schoolService.findClazzNameByStuName(stuName);
????}?
????/**
?????*?刪除某個(gè)學(xué)生對(duì)象
?????*/
????@RequestMapping("/deleteStuByStuName")
????public?String?deleteStuByStuName(String?stuName){
????????return?"刪除數(shù)據(jù):"+schoolService.deleteStuByStuName(stuName);
????}?
}
7)測(cè)試
http://localhost:8080/student/save
案例3:NamedQuery 查詢
使用 NameQuery 就是一個(gè)名稱映射一個(gè)查詢語句的查詢操作。
1)編輯 pom.xml 文件(與 CrudRepository 接口案例一樣)
2)創(chuàng)建 Student 和 Clazz 持久化類
先看 Student 類。
@Entity
@Table(name="tb_student")
//?查詢班級(jí)下的學(xué)生
@NamedQuery(name="Student.findStudentsByClazzName",query="select?s?from?Student?s?where?s.clazz.name?=??1")
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;
????//?學(xué)生與班級(jí)是多對(duì)一的關(guān)系,這里配置的是雙向關(guān)聯(lián)
????@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;
????}
????//?setXxx?和?getXxx?方法
}
再來看看 Clazz 類。
@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?;
????//?班級(jí)與學(xué)生是一對(duì)多的關(guān)聯(lián)
????@OneToMany(
???????????????fetch=FetchType.LAZY,
???????????????targetEntity=Student.class,
???????????????mappedBy="clazz"
????????????)?????
????private?Set?students?=?new?HashSet<>();
????public?Clazz()?{
????}
????//?班級(jí)對(duì)象
????public?Clazz(String?name)?{
????????this.name?=?name;
????}
????//?setXxx?和?getXxx?方法
}
3)創(chuàng)建 StudentRepository 和 ClazzRepository 數(shù)據(jù)訪問接口
先看 StudentRepository 類。
public?interface?StudentRepository?extends?JpaRepository<Student,?Integer>?{
????/**
?????*?查詢班級(jí)下的所有學(xué)生
?????*/
????List?findStudentsByClazzName(String?clazzName) ;
}
再看 ClazzRepository 類。
public?interface?ClazzRepository?extends?JpaRepository<Clazz,?Integer>?{????
}
4)創(chuàng)建 ShcoolService 業(yè)務(wù)層
@Service
public?class?ShcoolService?{
????//?注入數(shù)據(jù)訪問層接口對(duì)象?
????@Resource
????private?StudentRepository?studentRepository;
????@Resource
????private?ClazzRepository?clazzRepository;
????@Transactional
????public?void?saveClazzAll(List?clazzs) ?{
????????clazzRepository.saveAll(clazzs);
????}
????@Transactional
????public?void?saveStudentAll(List?students) ?{
????????studentRepository.saveAll(students);
????}
????public?List>?getStusByClazzName(String?clazzName)?{
????????//?查詢班級(jí)下的所有學(xué)生
????????List?students?=?studentRepository.findStudentsByClazzName(clazzName);
????????List>??results?=?new?ArrayList<>();?
????????//?遍歷查詢出的學(xué)生對(duì)象,提取姓名,年齡,性別信息
????????for(Student?student:students){
????????????Map?stu?=?new?HashMap<>();?
????????????stu.put("name",?student.getName());
????????????stu.put("age",?student.getAge());
????????????stu.put("sex",?student.getSex());
????????????results.add(stu);
????????}
????????return?results;
????}
}
5)創(chuàng)建 StudentController 控制器類
@RestController
@RequestMapping("/student")
public?class?StudentController?{
????@Resource
????private?ShcoolService?shcoolService;
????@RequestMapping("/save")
????public?String?save()?{
????????Clazz?clazz1?=?new?Clazz("架構(gòu)師001班");
????????Clazz?clazz2?=?new?Clazz("架構(gòu)師002班");
????????//?保存班級(jí)對(duì)象數(shù)據(jù)
????????List?clazzs?=?new?ArrayList<>();
????????clazzs.add(clazz1);
????????clazzs.add(clazz2);
????????shcoolService.saveClazzAll(clazzs);
????????Student?s1?=?new?Student("帥帥","廣州",18,'男',clazz1);
????????Student?s2?=?new?Student("小黃","廣州",17,'女',clazz1);
????????Student?s3?=?new?Student("小紅","廣州",15,'男',clazz2);
????????List?students?=?new?ArrayList<>();
????????students.add(s1);
????????students.add(s2);
????????students.add(s3);
????????shcoolService.saveStudentAll(students);
????????return?"保存學(xué)生成功";
????}
????/**
?????*?查詢某個(gè)班級(jí)下所有的學(xué)生姓名,年齡,性別
?????*/
????@RequestMapping("/getClazzStus")
????public?List>?getClazzStus(String?clazzName){
????????return?shcoolService.getStusByClazzName(clazzName);
????}?
}
6)測(cè)試
http://localhost:8080/student/save
案例4:Specification 查詢
1)編輯 pom.xml 文件(與 CrudRepository 接口案例一樣)
2)編輯 application.properties 文件(與 CrudRepository 接口案例一樣)
3)創(chuàng)建 Clazz 和 Student 持久化類
先來看 Clazz 類。
@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?;
????//?班級(jí)與學(xué)生是一對(duì)多的關(guān)聯(lián)
????@OneToMany(
???????????????fetch=FetchType.LAZY,
???????????????targetEntity=Student.class,
???????????????mappedBy="clazz"
????????????)?????
????private?Set?students?=?new?HashSet<>();
????public?Clazz()?{
????}
????//?班級(jí)對(duì)象
????public?Clazz(String?name)?{
????????this.name?=?name;
????}
????//?setXxx?和?getXxx?方法
}
再來看看 Student 類。
@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;
????//?學(xué)生與班級(jí)是多對(duì)一的關(guān)系,這里配置的是雙向關(guān)聯(lián)
????@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;
????}
????//?setXxx?和?getXxx?方法
}
4)創(chuàng)建 ClazzRepository 和 StudentRepository 數(shù)據(jù)訪問接口
先看 ClazzRepository 類。
public?interface?ClazzRepository?extends?JpaRepository<Clazz,?Integer>?,JpaSpecificationExecutor<Clazz>{
}
再看 StudentRepository 類。
public?interface?StudentRepository?extends?JpaRepository<Student,Integer>,JpaSpecificationExecutor<Student>{
}
5)創(chuàng)建 ShcoolService 業(yè)務(wù)層
@Service
public?class?ShcoolService?{
????//?注入數(shù)據(jù)訪問層接口對(duì)象?
????@Resource
????private?StudentRepository?studentRepository;
????@Resource
????private?ClazzRepository?clazzRepository;
????@Transactional
????public?void?saveClazzAll(List?clazzs) ?{
????????clazzRepository.saveAll(clazzs);
????}
????@Transactional
????public?void?saveStudentAll(List?students) ?{
????????studentRepository.saveAll(students);
????}
????/**
?????*?根據(jù)性別查詢學(xué)生信息
?????*/
????@SuppressWarnings("serial")
????public?List>?getStusBySex(char?sex)?{
????????List?students?=?studentRepository.findAll(new?Specification()?{
????????????@Override
????????????public?Predicate?toPredicate(Root?root,?CriteriaQuery>?query,
????????????????????CriteriaBuilder?cb) ?{
???????????????Predicate?p1?=?cb.equal(root.get("sex"),?sex);
???????????????return?p1;
????????????}
????????});
????????List>??results?=?new?ArrayList<>();?
????????for(Student?student:students){
????????????Map?stu?=?new?HashMap<>();?
????????????stu.put("name",?student.getName());
????????????stu.put("age",?student.getAge());
????????????stu.put("sex",?student.getSex());
????????????results.add(stu);
????????}
????????return?results;
????}
????/**
?????*?動(dòng)態(tài)查詢學(xué)生信息?
?????*?可以根據(jù)學(xué)生對(duì)象的姓名(模糊匹配)
?????*?地址查詢(模糊匹配)、性別、班級(jí)查詢學(xué)生信息?
?????*?如果沒有傳輸參數(shù),默認(rèn)查詢所有的學(xué)生信息
?????*/
????@SuppressWarnings("serial")
????public?List>?getStusByDynamic(Student?student)?{
????????List?students?=?studentRepository.findAll(new?Specification()?{
????????????@Override
????????????public?Predicate?toPredicate(Root?root,?CriteriaQuery>?query,
????????????????????CriteriaBuilder?cb) ?{
????????????????//?本集合用于封裝查詢條件
????????????????List?predicates?=?new?ArrayList();??
????????????????if(student!=null){
????????????????????/**?是否傳入了姓名來查詢??*/
????????????????????if(!StringUtils.isEmpty(student.getName())){
????????????????????????predicates.add(cb.like(root.?get("name"),"%"?+?student.getName()?+?"%"));
????????????????????}
????????????????????/**?是否傳入了地址來查詢??*/
????????????????????if(!StringUtils.isEmpty(student.getAddress())){
????????????????????????predicates.add(cb.like(root.?get("address"),"%"?+?student.getAddress()?+?"%"));
????????????????????}
????????????????????/**?是否傳入了性別來查詢?*/
????????????????????if(student.getSex()?!=?'\0'){
????????????????????????predicates.add(cb.equal(root.?get("sex"),student.getSex()));
????????????????????}
????????????????????/**?判斷是否傳入了班級(jí)信息來查詢?*/
????????????????????if(student.getClazz()!=null?&&?!StringUtils.isEmpty(student.getClazz().getName())){
????????????????????????root.join("clazz",?JoinType.INNER);
????????????????????????Path?clazzName?=?root.get("clazz").get("name");
????????????????????????predicates.add(cb.equal(clazzName,?student.getClazz().getName()));
????????????????????}
????????????????}
????????????????return?query.where(predicates.toArray(new?Predicate[predicates.size()])).getRestriction();
????????????}
????????});
????????List>??results?=?new?ArrayList<>();?
????????for(Student?stu?:students){
????????????Map?stuMap?=?new?HashMap<>();?
????????????stuMap.put("name",?stu.getName());
????????????stuMap.put("age",?stu.getAge());
????????????stuMap.put("sex",?stu.getSex());
????????????stuMap.put("address",?stu.getAddress());
????????????stuMap.put("clazzName",?stu.getClazz().getName());
????????????results.add(stuMap);
????????}
????????return?results;
????}
????/**
?????*?分頁查詢某個(gè)班級(jí)的學(xué)生信息
?????*/
????@SuppressWarnings("serial")
????public?Page?getStusByPage(String?clazzName?,?int?pageIndex?,?int?pageSize?)? {
????????//?指定排序參數(shù)對(duì)象:根據(jù)id,進(jìn)行降序查詢
????????Sort?sort?=?new?Sort(Sort.Direction.DESC,?"id");
????????//?分頁查詢學(xué)生信息,返回分頁實(shí)體對(duì)象數(shù)據(jù)
????????//?pages對(duì)象中包含了查詢出來的數(shù)據(jù)信息,以及與分頁相關(guān)的信息
????????Page?pages?=?studentRepository.findAll(new?Specification()?{
????????????@Override
????????????public?Predicate?toPredicate(Root?root,?CriteriaQuery>?query,
????????????????????CriteriaBuilder?cb) ?{
????????????????root.join("clazz",?JoinType.INNER);
????????????????Path?cn?=?root.get("clazz").get("name");
????????????????Predicate?p1?=?cb.equal(cn,?clazzName);
????????????????return?p1?;
????????????}
????????},PageRequest.of(pageIndex-1,?pageSize,?sort));
????????return?pages;
????}
}
6)創(chuàng)建分頁對(duì)象
添加 nx.vo 文件夾,然后創(chuàng)建分頁對(duì)象,具體如下:
public?class?PageData?{
????//?定義一個(gè)變量用于存放當(dāng)前頁碼?
????private?int?pageIndex;
????//?定義一個(gè)變量用于保存滿足查詢條件下用于分頁的數(shù)據(jù)總量
????private?long?totalCount??;
????//?定義一個(gè)變量用于保存當(dāng)前條件下總共可以分的總頁數(shù)
????private?int?pageSize?;
????//?定義一個(gè)變量用于保存當(dāng)前頁碼查詢出的數(shù)據(jù)總量
????private?int?pageNum;
????//?定義一個(gè)變量用于保存當(dāng)前查詢出來的學(xué)生信息?
????private?List>?stuDatas?=?new?ArrayList<>();
????//?setXxx?和?getXxx?方法?????
}
7)創(chuàng)建 StudentController 控制器類
@RestController
@RequestMapping("/student")
public?class?StudentController?{
????//?注入ShcoolService
????@Resource
????private?ShcoolService?shcoolService;
????@RequestMapping("/save")
????public?String?save()?{
????????Clazz?clazz1?=?new?Clazz("架構(gòu)師001班");
????????Clazz?clazz2?=?new?Clazz("架構(gòu)師002班");
????????//?保存班級(jí)對(duì)象數(shù)據(jù)
????????List?clazzs?=?new?ArrayList<>();
????????clazzs.add(clazz1);
????????clazzs.add(clazz2);
????????shcoolService.saveClazzAll(clazzs);
????????Student?s1?=?new?Student("小黃","廣州",17,'男',clazz1);
????????Student?s2?=?new?Student("小紅","成都",15,'女',clazz1);
????????Student?s3?=?new?Student("小綠","上海",15,'男',clazz1);
????????Student?s4?=?new?Student("小豆","北京",15,'女',clazz2);
????????Student?s5?=?new?Student("小牛","西藏",15,'男',clazz2);
????????Student?s6?=?new?Student("小蘭","黑龍江",17,'女',clazz2);
????????List?students?=?new?ArrayList<>();
????????students.add(s1);
????????students.add(s2);
????????students.add(s3);
????????students.add(s4);
????????students.add(s5);
????????students.add(s6);
????????shcoolService.saveStudentAll(students);
????????return?"保存學(xué)生成功";
????}
????@RequestMapping("/getStusBySex")
????public?List>?getStusBySex(char?sex){
????????return?shcoolService.getStusBySex(sex);
????}?
????//?動(dòng)態(tài)的查詢學(xué)生信息?
????@RequestMapping("/getStusByDynamic")
????public?List>?getStusByDynamic(Student?student)?{
????????return?shcoolService.getStusByDynamic(student);
????}
????//?分頁查詢某個(gè)班級(jí)下的學(xué)生信息
????@RequestMapping("/getStusByPage")
????public?PageData?getStusByPage(String?clazzName?,?int?pageIndex?,?int?pageSize?)?{
????????//?分頁查詢某個(gè)班級(jí)的學(xué)生信息
????????Page?page?=?shcoolService.getStusByPage(clazzName?,?pageIndex?,?pageSize);
????????//?對(duì)查詢出來的結(jié)果數(shù)據(jù)進(jìn)行分析
????????List?students?=?page.getContent();
????????List>?stuDatas?=?new?ArrayList<>();
????????for(Student?stu?:students){
????????????Map?stuMap?=?new?HashMap<>();?
????????????stuMap.put("id",?stu.getId());
????????????stuMap.put("name",?stu.getName());
????????????stuMap.put("age",?stu.getAge());
????????????stuMap.put("sex",?stu.getSex());
????????????stuMap.put("address",?stu.getAddress());
????????????stuMap.put("clazzName",?clazzName);
????????????stuDatas.add(stuMap);
????????}
????????//?將分頁查詢出的結(jié)果數(shù)據(jù)進(jìn)行分析,然后把數(shù)據(jù)存入到PageData對(duì)象中去保存起來響應(yīng)給瀏覽器展示?
????????PageData?data?=?new?PageData();
????????data.setStuDatas(stuDatas);
????????data.setPageIndex(page.getNumber()+1);
????????data.setPageSize(page.getTotalPages());
????????data.setTotalCount(page.getTotalElements());
????????data.setPageNum(page.getSize());
????????return?data?;
????}?
}
8)測(cè)試
http://localhost:8080/student/save

Java后端編程
更多Java推文,關(guān)注公眾號(hào)
評(píng)論
圖片
表情
