一、建表
- 创建班级表
create table clazz( clazzId int primary key auto_increment, clazzName varchar(8) not null );
- 创建学生信息表
create table studentInfo( id int primary key auto_increment, studentName varchar(32) not null , sex varchar(8) not null , age int not null , phone varchar(32) not null , address varchar(128) not null , cId int references clazz(clazzId) );
二、引入相关配置,配置application.properties 文件
-
引入依赖
<!--mysql 相关依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!-- 阿里 数据源 druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.2.5.RELEASE</version> </dependency> <!--mybatis 依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency>
-
配置application.properties 文件
#别名 mybatis.type-aliases-package=com.sys.examtest.domain #驱动配置可省略,springboot可以自动识别 spring.datasource.driver-class-name =com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/student?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.username =root spring.datasource.password =root #如果不配置阿里的druid,会自动使用默认的数据源 (com.zaxxer.hikari.HikariDataSource) spring.datasource.type = com.alibaba.druid.pool.DruidDataSource #控制台显示SQL mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl #freemarker基础配置 # 是否开启thymeleaf缓存,本地为false,生产建议为true spring.freemarker.cache=false spring.freemarker.charset=UTF-8 spring.freemarker.allow-request-override=false spring.freemarker.check-template-location=true #类型 spring.freemarker.content-type=text/html spring.freemarker.expose-request-attributes=true spring.freemarker.expose-session-attributes=true #文件后缀 spring.freemarker.suffix=.ftl #路径 spring.freemarker.template-loader-path=classpath:/templates/fr
-
启动类加注解
@SpringBootApplication @MapperScan(basePackages = {"com.sys.examtest.mapper"}) //mybatis注解 public class ExamTestApplication { public static void main(String[] args) { SpringApplication.run(ExamTestApplication.class, args); } }
三、编写代码
-
实体类
班级实体类public class Clazz { private Integer clazzId; private String clazzName; //学生集合,一对多查询 private List<Student> list = new ArrayList<>(); public Integer getClazzId() { return clazzId; } public void setClazzId(Integer clazzId) { this.clazzId = clazzId; } public String getClazzName() { return clazzName; } public void setClazzName(String clazzName) { this.clazzName = clazzName; } public List<Student> getList() { return list; } public void setList(List<Student> list) { this.list = list; } }
学生实体类
public class Student { private Integer id; private String studentName; private String sex; private Integer age; private String phone; private String address; private Integer cId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getCId() { return cId; } public void setCId(Integer cId) { this.cId = cId; } }
-
一对多查询
定义一个根据班级id查询学生的方法public interface StudentMapper { //根据学生表中的班级id,查询对应班级的学生 @Select("select * from studentInfo where cId = #{id}") public Student findById(Integer id); }
查询班级信息以及对应班级的学生信息
@Repository public interface ClazzMapper { /** * 查询所有班级及学生信息 * @return */ @Select("select * from clazz") @Results(id = "clazz_map", value = { @Result(id = true,property="clazzId" ,column="clazzId"), @Result(column="clazzName", property="clazzName"), @Result(property = "list",column = "clazzId", many = @Many(select = "com.sys.examtest.mapper.StudentMapper.findById")) }) public List<Clazz> findAll(); }
property="clazzId"
:表示要将返回的查询结果赋值给 clazz 的 clazzId 属性
property="clazzName"
:表示要将返回的查询结果赋值给 clazz 的 clazzName 属性
property="list"
:表示要将返回的查询结果赋值给 clazz 的 list 集合属性
many 表示这是一个一对多的查询
@Many(select = “方法全路径”) 表示我们调用的方法, 方法参数 clazzId 就是上面column指定的列值 -
controller层调用(测试)
@Controller @RequestMapping("/clazz") public class ClazzController { @Autowired private ClazzMapper clazzMapper; @RequestMapping("/findAll") public ModelAndView findAll(ModelAndView model){ List<Clazz> clazzList = clazzMapper.findAll(); model.addObject("list",clazzList); model.setViewName("/findAll"); return model; } }
-
findAll.ftl 文件遍历集合
<#list list as item> ${item} <#list item.list as stu> ${stu} <#list> <#list>
<table> <tr> <td>班级序号</td> <td>班级名称</td> </tr> <#list list as item> <tr> <td>${item.clazzId}</td> <td>${item.clazzName}</td> </tr> <tr> <th>学生序号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>电话</th> <th>地址</th> </tr> <#list item.list as stu> <tr> <td>${stu.id}</td> <td>${stu.studentName}</td> <td>${stu.sex}</td> <td>${stu.age}</td> <td>${stu.phone}</td> <td>${stu.address}</td> </tr> </#list> </#list> </table>
四、一对一 和 一对多 总结
共同点:
-无论是一对一还是一对多,都是通过附属查询来实现的,我们需要定义这个附属查询方法。
--在主查询方法中通过@One、@Many指定附属查询方法的全路径。
---都通过column来传递参数给附属方法。
不同点:
一对一,那么附属方法返回的是一个单独的对象
一对多,那么附属方法返回的是一个对象集合