需求
现有一个班级,班级内有多个学生,1个老师,该场景为多对一,一对多
要求使用MyBatis查出学生对应的老师,及每个老师教的学生。
数据表准备
student:
CREATE TABLE `student` (
`id` int(10) NOT NULL,
`name` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tid` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
)
teacher:
CREATE TABLE `teacher` (
`id` int(10) NOT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
)
创建好表格后随便设立几个学生信息和老师信息,然后我们就可以开始创建我们的程序了。创建spring项目,然后接下来配置pom文件,主要是应用数据库相关依赖。
程序创建:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tlkj</groupId>
<artifactId>select</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>select</name>
<description>select</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!--thymeleaf模板引擎配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--Web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--MyBatis配置-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.tlkj.select.SelectApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后在resource文件夹下创建spring可以识别的application.yml文件。
application.yml
server:
port: 8081
spring:
datasource:
name: test #数据库名
url: jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8
username: root #用户名
password: 123456 #密码
driver-class-name: com.mysql.cj.jdbc.Driver #数据库链接驱动
mybatis:
mapper-locations[0]: classpath:mapper/*.xml #配置映射文件
type-aliases-package: com.example.select.bean #配置实体类
Bean文件
创建Bean文件,用于封装学生和老师的属性。封装之后记得同时生成他们的setter和getter。
学生的Bean:
public class StuBean {
private Integer id;
private String name;
private Integer tid;
private TeaBean teaBean;
}
老师的Bean:
public class TeaBean {
private Integer id;
private String name;
private List<StuBean> studentList;
}
值得注意的事情是:学生Bean里面有一个老师的信息,即tid,也就是老师的id。然后,老师的Bean里面有一个List集合用于存储老师名下学生的信息。
然后就是创建mapper.xml文件,也就是重点。
一对多查询:(一个老师查询他的所有学生)
<select id="teac" parameterType="com.tlkj.select.bean.TeaBean" resultMap="TeacherStudent">
select * from teacher where id = #{id}
</select>
<resultMap id="TeacherStudent" type="com.tlkj.select.bean.TeaBean">
<result property="id" column="id"/>
<collection property="studentList" javaType="ArrayList" ofType="com.tlkj.select.bean.StuBean" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" parameterType="com.tlkj.select.bean.StuBean" resultType="com.tlkj.select.bean.StuBean">
select * from student where tid = #{id}
</select>
多对一查询:(从学生查老师)
<select id="stu" parameterType="com.tlkj.select.bean.StuBean" resultMap="getStudentTeacher">
select * from student where id = #{id}
</select>
<resultMap id="getStudentTeacher" type="com.tlkj.select.bean.StuBean">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="tid" column="tid"/>
<association property="teaBean" column="tid" javaType="com.tlkj.select.bean.TeaBean" select="getTeacher"/>
</resultMap>
<select id="getTeacher" parameterType="com.tlkj.select.bean.TeaBean" resultType="com.tlkj.select.bean.TeaBean">
select * from teacher where id = #{tid}
</select>
mapper.java
StuMapper,java
@Mapper
public interface StuMapper {
StuBean stu(@Param("id") Integer id ,@Param("name")String name,@Param("tid")Integer tid);
}
TeaMapper.java
@Mapper
public interface TeaMapper {
TeaBean teac(@Param("id") Integer id, @Param("name") String name);
}
Mapper里面值得注意的事情是要使用@Param注释每一个变量。
然后就是常规的service层。
service.java
首先是两个查询方式的接口:
public interface StuService {
StuBean stud(Integer id ,String name,Integer tid);
}
public interface TeaService {
TeaBean teach(Integer id,String name);
}
然后就是两个接口的实现类
@Service
public class StuServiceImpl implements StuService {
@Autowired(required = false)
private StuMapper stuMapper;
@Override
public StuBean stud(Integer id ,String name,Integer tid){
return stuMapper.stu(id, name, tid);
}
}
@Service
public class TeaServiceImpl implements TeaService {
@Autowired(required = false)
private TeaMapper teaMapper;
@Override
public TeaBean teach(Integer id, String name) {
return teaMapper.teac(id,name);
}
}
controller.java
这一层主要是处理一下前端过来的请求。以及部分业务处理。
@RestController
public class StuController {
@Autowired
StuService stuService;
@RequestMapping(value = "/stuselect",method = RequestMethod.POST)
public String studen(@RequestBody StuBean stuBean){
StuBean stuBean1 = stuService.stud(stuBean.getId(),stuBean.getName(),stuBean.getTid());
if (stuBean1==null){
return "查询失败";
}
else{
return "学生:"+stuBean1.getName()+" 的老师是 "+ stuBean1.getTeaBean().getName();
}
}
}
@RestController
public class TeaController {
@Autowired
TeaService teaService;
@RequestMapping(value = "/teaselect",method = RequestMethod.POST)
public String teacher(@RequestBody TeaBean teaBean1){
TeaBean teaBean = teaService.teach(teaBean1.getId(),teaBean1.getName());
if (teaBean==null){
return "查询失败";
}
else{
String str = teaBean.getName()+"的学生是: ";
System.out.println(teaBean.getStudentList().size());
for (int i =0;i <teaBean.getStudentList().size();i++) {
String str1 = teaBean.getStudentList().get(i).getName();
str = new StringBuffer().append(str).append(str1).append(" ").toString();
}
return str;
}
}
}
这个地方需要注意的事情是,我是通过前postman发送post请求过来的,需要用到@RequeBody注解。以及后面查询老师对应学生信息的时候,学生集合中读取学生名字,要调用get方法然后再调用getName方法。
启动类:
@MapperScan("com.tlkj.select.mapper.*")
@SpringBootApplication
public class SelectApplication {
public static void main(String[] args) {
SpringApplication.run(SelectApplication.class, args);
}
}
启动类上方记得添加@MapperScan注释。
常见错误:
值得注意的事情,也就是我犯错的事情:
1.查询过程中的mybatis的文件中的各个标签的含义。这个地方很容易犯错,常见的问题是,配置的id属性不对应,导致mapper.java和mapper.xml文件没有对应上。
2.postman的请求的接收,需要在controller的方法的参数列表里@RequeBody注解。
3.记得添加@Mapper,@Controller,@Service注解,以及主启动类上还得添加@MapperScan注解。以及在controller和service的实体类里面记得添加@Autowired注解。