Spring-Data-Jpa关联查询

this.stuList = stuList;

}

public Clazz(String name) {

this.name = name;

}

public Clazz() {

}

}

从上述代码可以看出,班级与学生是一对多的关系,一个班级可以有多名学生,此处做的是双向关联,即在班级对象中关联了学生对象,在学生对象中也关联了班级对象。

2、定义数据访问层接口

之后在repository包下新建一个接口,命名为StuRepository,该接口继承JpaRepository接口,以持久化对象Stu作为JpaRepository的第一个类型参数,表示当前所操作的持久化对象类型,Integer作为JpaRepository的第二个类型参数,用于指定ID类型,同时创建一个接口名称为ClazzRepository,继承JpaRepository的接口,用于访问班级信息的数据。

ClazzRepository.java接口

import com.mcy.springdatajpa.entity.Clazz;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ClazzRepository extends JpaRepository<Clazz, Integer> {

}

StuRepository.java接口(包含了一些关联查询)

import com.mcy.springdatajpa.entity.Stu;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Modifying;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.query.Param;

import java.util.List;

import java.util.Map;

public interface StuRepository extends JpaRepository<Stu, Integer> {

/**

  • 根据班级名称查询这个班级所有学生的信息

  • 相当于JPQL语句:select s from stu s where s.clazzname = ?1

  • @param clazzNam

  • @return

*/

List findByClazz_name(String clazzNam);

/**

  • 根据班级名称查询这个班级所有学生的信息

  • 相当于JPQL语句:select s from stu s where s.clazzname = ?1

  • @param clazzNam

  • @return

*/

List findByClazzName(String clazzNam);

/**

  • @Query方法

  • 根据班级名称查询这个班级所有学生的信息

  • ?1此处使用的是参数的位置,代表的是第一个参数

  • 此写法与findByClazz_name方法实现的功能完全一致

  • @param clazzName

  • @return

*/

@Query(“select s from Stu s where s.clazz.name = ?1”)

List findStuByClazzName(String clazzName);

/**

  • 使用@Query注解的形式,查询某个班级下所有学生的姓名和性别

  • @param clazzName

  • @return

*/

@Query(“select new Map(s.name, s.sex) from Stu s where s.clazz.name = ?1”)

List<Map<String, Object>> findNameAndSexByClazzName(String clazzName);

/**

  • 使用@Query注解的形式,查询某个班级下某种性别的所有学生的姓名

  • 上面方法用的是参数的位置来查询的,spring-data-jpa中还支持用名称来匹配查询,使用格式“:参数名称”引用

  • @param clazzName

  • @param sex

  • @return

*/

@Query(“select s.name from Stu s where s.clazz.name=:clazzName and s.sex=:sex”)

List findNameByClazzNameAndSex(@Param(“clazzName”)String clazzName, @Param(“sex”)char sex);

/**

  • 使用@Query注解的形式,查询某个学生属于哪个班级

  • @param stuName

  • @return

*/

@Query(“select c.name from Clazz c inner join c.stuList s where s.name = ?1”)

String findClazzNameByStuName(String stuName);

/**

  • 执行更新查询,使用@Query与@Modifying可以执行更新操作

  • 例如根据姓名删除学生

  • @param stuName

  • @return

*/

@Modifying

@Query(“delete from Stu s where s.name = ?1”)

Integer deleteStuByStuName(String stuName);

}

  1. 从上述代码中可以看出,List findByClazz_name(String clazzNam)和findByClazzName(String clazzNam)方法是关联查询的方法,关联的属性可以用下划线“_”链接,或者根据Spring-Data-Jpa命名规范去查询,此方法定义在学生对象的数据访问层接口下,相当于JPQL语句:select s from stu s where s.clazzname = ?1

  2. @Query(“select s from Stu s where s.clazz.name = ?1”)定义在方法List findStuByClazzName(String clazzName)上,与List findByClazz_name(String clazzNam)方法的功能是完全一致的,只是这里采用的是@Query注解的形式进行查询。@Query注解中可以直接定义JPQL语句进行数据的访问操作,@Query查询摆脱了像命名查询那样的约束,将查询直接在相应的接口方法上声明,结构更为清晰,这是Spring Data的特有实现,非常方便。JPQL语句中“?1”指代的是取方法形参列表中第1个参数值,1代表的是参数位置,以此类推。

  3. @Query(“select new Map(s.name, s.sex) from Stu s where s.clazz.name = ?1”)List<Map<String, Object>> findNameAndSexByClazzName(String clazzName);此方法使用JPQL语句直接返回List<Map<String, Object>>对象。

  4. @Query(“select s.name from Stu s where s.clazz.name=:clazzName and s.sex=:sex”)List findNameByClazzNameAndSex(@Param(“clazzName”)String clazzName, @Param(“sex”)char sex)之前的方法是使用参数的位置来获取参数的值的,除此之外,SpringDataJpa还支持用名称来匹配获取参数的值,使用格式为“:参数名称”,如上面方法所示,@Param注解用于声明参数的名称,“:参数名称”,用于提前对应参数的值。

  5. @Query(“select c.name from Clazz c inner join c.stuList s where s.name = ?1”)String findClazzNameByStuName(String stuName)此方法,实现了关联查询,查询某个学生所属的班级的名称。

  6. @Modifying@Query(“delete from Stu s where s.name = ?1”)

Integer deleteStuByStuName(String stuName)在此方法中,SpringDataJpa支持使用@Modifying和@Query注解组合更新查询操作,上述方法即使用了此操作删除了某个学生数据。

3、定义业务层类

在service包下新建一个SchoolService类,代码如下(几个关联查询方法)

import com.mcy.springdatajpa.entity.Clazz;

import com.mcy.springdatajpa.entity.Stu;

import com.mcy.springdatajpa.repository.ClazzRepository;

import com.mcy.springdatajpa.repository.StuRepository;

import com.mcy.springdatajpa.repository.StudentRepository;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

@Service

public class SchoolService {

//注入数据访问层接口对象

@Resource

private StuRepository stuRepository;

@Resource

private ClazzRepository clazzRepository;

//事务管理

@Transactional

public void saveClazzAll(List clazzes){

clazzRepository.saveAll(clazzes);

}

@Transactional

public void saveStuAll(List stus){

stuRepository.saveAll(stus);

}

public List<Map<String, Object>> getStusByClazzName(String clazzName){

//使用"-",驼峰式命名和@Query查询方式结果一致

List stus = stuRepository.findByClazz_name(clazzName);

//List stus = stuRepository.findByClazzName(clazzName);

//List stus = stuRepository.findStuByClazzName(clazzName);

List<Map<String, Object>> results = new ArrayList<>();

//遍历查询出的学生对象,提取姓名,年龄,性别信息

for(Stu stu : stus){

Map<String, Object> s = new HashMap<>();

s.put(“name”, stu.getName());

s.put(“age”, stu.getAge());

s.put(“sex”, stu.getSex());

results.add(s);

}

return results;

}

public List<Map<String, Object>> findNameAndSexByClazzName(String clazzName){

return stuRepository.findNameAndSexByClazzName(clazzName);

}

public List findNameByClazzNameAndSex(String clazzName, char sex){

return stuRepository.findNameByClazzNameAndSex(clazzName, sex);

}

public String findClazzNameByStuName(String stuName){

return stuRepository.findClazzNameByStuName(stuName);

}

@Transactional

public Integer deleteStuByStuName(String stuName){

return stuRepository.deleteStuByStuName(stuName);

}

}

在业务层中需要注入数据访问层对象,在上述代码中是通过@Resources注解将StuRepository和ClazzRepository接口对应的实现类对象注入进来的。

4、定义控制器类

在controller包下新建一个StuController类,代码如下(访问方法)。

import com.mcy.springdatajpa.entity.Clazz;

import com.mcy.springdatajpa.entity.Stu;

import com.mcy.springdatajpa.service.SchoolService;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

@RestController

@RequestMapping(“/stu”)

public class StuController {

//注入ShcoolService

@Resource

private SchoolService schoolService;

//保存,初始化数据

@RequestMapping(“/save”)

public String save(){

Clazz clazz1 = new Clazz(“软件工程1班”);

Clazz clazz2 = new Clazz(“软件工程2班”);

//保存班级对象数据

List clazzs = new ArrayList<>();

clazzs.add(clazz1);

clazzs.add(clazz2);

schoolService.saveClazzAll(clazzs);

Stu stu1 = new Stu(“张三”, “湖北”, 20, ‘男’, clazz1 );

Stu stu2 = new Stu(“李四”, “湖北”, 18, ‘女’, clazz1 );

Stu stu3 = new Stu(“王五”, “湖北”, 17, ‘男’, clazz2 );

List stus = new ArrayList<>();

stus.add(stu1);

stus.add(stu2);

stus.add(stu3);

schoolService.saveStuAll(stus);

return “数据保存成功!”;

}

/**

  • 查询某个班级所有学生的姓名,年龄,性别

  • @param clazzName

  • @return

*/

@RequestMapping(“/getClazzStus”)

public List<Map<String, Object>> getClazzStus(String clazzName){

return schoolService.getStusByClazzName(clazzName);

}

/**

  • 查询某个班级所有学生的姓名,性别

  • @param clazzName

  • @return

*/

@RequestMapping(“/findNameAndSexByClazzName”)

public List<Map<String, Object>> findNameAndSexByClazzName(String clazzName){

return schoolService.findNameAndSexByClazzName(clazzName);

}

/**

  • 查询某个班级某种性别的所有学生的姓名

  • @param clazzName

  • @param sex

  • @return

*/

@RequestMapping(“/findNameByClazzNameAndSex”)

public List findNameByClazzNameAndSex(String clazzName, Character sex){

return schoolService.findNameByClazzNameAndSex(clazzName, sex);

}

/**

  • 查询某个学生属于哪个班级

  • @param stuName

  • @return

*/

@RequestMapping(“/findClazzNameByStuName”)

public String findClazzNameByStuName(String stuName){

return schoolService.findClazzNameByStuName(stuName);

}

/**

  • 删除某个学生对象

  • @param stuName

  • @return

*/

@RequestMapping(“/deleteStuByStuName”)

public String deleteStuByStuName(String stuName){

return “删除数据:”+schoolService.deleteStuByStuName(stuName);

}

}

测试应用


1、测试应用

启动MySQL数据库,在数据库中创建名为jpa的数据库。springboot项目启动后,JPA会在数据库中自动创建持久化类对应的tb_stu和tb_clazz表。

测试添加学生和班级信息,在浏览器中输入http://localhost:8080/stu/save地址,请求会提交给StuController类的save方法进行处理,执行完成返回“数据保存成功!”

查看数据库中的数据如图(StuController类的save方法中数据对应):


自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

分享一些系统的面试题,大家可以拿去刷一刷,准备面试涨薪。

这些面试题相对应的技术点:

  • JVM
  • MySQL
  • Mybatis
  • MongoDB
  • Redis
  • Spring
  • Spring boot
  • Spring cloud
  • Kafka
  • RabbitMQ
  • Nginx

大类就是:

  • Java基础
  • 数据结构与算法
  • 并发编程
  • 数据库
  • 设计模式
  • 微服务
  • 消息中间件

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?

程序员,每个月给你发多少工资,你才会想老板想的事?
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
Spring

  • Spring boot
  • Spring cloud
  • Kafka
  • RabbitMQ
  • Nginx

大类就是:

  • Java基础
  • 数据结构与算法
  • 并发编程
  • 数据库
  • 设计模式
  • 微服务
  • 消息中间件

[外链图片转存中…(img-87a4CWnb-1712074890520)]

[外链图片转存中…(img-rw306lxI-1712074890521)]

[外链图片转存中…(img-npv9u1yJ-1712074890521)]

[外链图片转存中…(img-9liAzphG-1712074890521)]

[外链图片转存中…(img-sM1tbQJX-1712074890521)]

[外链图片转存中…(img-mfkuTYIw-1712074890522)]

[外链图片转存中…(img-nHKi1ln3-1712074890522)]

[外链图片转存中…(img-JiQa84vM-1712074890522)]

[外链图片转存中…(img-lFinWeC9-1712074890522)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值