MyBatis关联映射
目录
一、什么是关联注解?
MyBatis关联注解是在使用MyBatis进行数据库操作时,用于处理对象之间关联关系的注解。这些注解使得开发者可以更加灵活地处理数据库中的关联数据,而无需编写复杂的XML映射文件。
二、数据库建表
1.学生表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Sname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`t_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '张三', '男', 18, 1);
INSERT INTO `student` VALUES (2, '李四', '女', 18, 1);
INSERT INTO `student` VALUES (3, '王五', '男', 18, 1);
INSERT INTO `student` VALUES (4, '小白', '女', 18, 1);
INSERT INTO `student` VALUES (5, '小黑', '男', 18, 1);
INSERT INTO `student` VALUES (6, '小红', '女', 20, 2);
INSERT INTO `student` VALUES (7, '小李', '男', 20, 2);
INSERT INTO `student` VALUES (8, '小张', '女', 20, 2);
INSERT INTO `student` VALUES (9, '小赵', '男', 20, 2);
INSERT INTO `student` VALUES (10, '小王', '女', 20, 2);
SET FOREIGN_KEY_CHECKS = 1;
2.教师表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Tname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES (1, '张老师');
INSERT INTO `teacher` VALUES (2, '李老师');
SET FOREIGN_KEY_CHECKS = 1;
三、一般查询
select student.*,teacher.* from student left join teacher on student.t_id=teacher.id
结果如下
在idea中
(1)创建StudentTeacher类
按照表头进行变量属性设置,并设置getter&setter函数,重写toString方法
package com.qcby.entity;
public class StudentTeacher {
private Integer id;
private String Sname;
private String sex;
private Integer age;
private Integer t_id;
private String Tname;
@Override
public String toString() {
return "StudentTeacher{" +
"id=" + id +
", Sname='" + Sname + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", t_id=" + t_id +
", Tname='" + Tname + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
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 Integer getT_id() {
return t_id;
}
public void setT_id(Integer t_id) {
this.t_id = t_id;
}
public String getTname() {
return Tname;
}
public void setTname(String tname) {
Tname = tname;
}
}
(2)mapper层
<select id="findStudentTeacher" resultType="com.qcby.entity.StudentTeacher">
SELECT student.*,teacher.* FROM student LEFT JOIN teacher on student.t_id = teacher.id
</select>
(3)Dao接口
package com.qcby.dao;
import com.qcby.entity.StudentTeacher;
import java.util.List;
public interface StudentTeacherDao {
List<StudentTeacher> findStudentTeacher();
}
(4)Test类
package com.qcby;
import com.qcby.dao.StudentTeacherDao;
import com.qcby.entity.StudentTeacher;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class StudentTeacherTest {
private InputStream in = null;
private SqlSession session = null;
private StudentTeacherDao mapper = null;
@Before //前置通知, 在方法执行之前执行
public void init() throws IOException {
//加载主配置文件,目的是为了构建SqlSessionFactory对象
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//通过SqlSessionFactory工厂对象创建SqlSesssion对象
session = factory.openSession();
//通过Session创建UserDao接口代理对象
mapper = session.getMapper(StudentTeacherDao.class);
}
@After //@After: 后置通知, 在方法执行之后执行 。
public void destory() throws IOException {
//释放资源
session.close();
in.close();
}
@Test
public void findStudentTeacher(){
List<StudentTeacher> studentTeacher=mapper.findStudentTeacher();
for (StudentTeacher s:studentTeacher) {
System.out.println(s.toString());
}
}
}
(5)测试结果
四、关联映射:一对一、多对一
1、第一种形式 连表查询
(1)创建Student实体类
我们的目标是找到学生对应的老师:这个思路为先找到所有的学生,然后找到其所对应的老师
学生类
package com.qcby.entity;
public class Student {
private Integer id;
private String Sname;
private String sex;
private Integer age;
private Integer t_id;
//重要
private Teacher teacher;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", Sname='" + Sname + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", t_id=" + t_id +
// ", teacher=" + teacher +
'}';
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
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 Integer getT_id() {
return t_id;
}
public void setT_id(Integer t_id) {
this.t_id = t_id;
}
}
教师类
public class Teacher {
private Integer id;
private String Tname;
}
其中很重要的一行,这一行一定要加上
private Teacher teacher;
(2)mapper层
<select id="findStudentTeacher" resultMap="StudentTeacher">
SELECT student.id,student.Sname,teacher.Tname FROM student LEFT JOIN teacher on student.t_id = teacher.id
</select>
<resultMap id="StudentTeacher" type="com.qcby.entity.Student">
<result property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
<association property="teacher" javaType="com.qcby.entity.Teacher">
<result property="id" column="id"/>
<result property="Tname" column="Tname"/>
</association>
</resultMap>
resultMap
是MyBatis中一个非常强大的特性,它用于定义结果映射。允许你将数据库中的列映射到Java对象的属性上,尤其是在处理复杂类型(如关联对象)时非常有用。以下是一些解释:
- resultMap标签:
id="StudentTeacher"
:这是resultMap
的唯一标识符,用于在查询语句中引用这个映射配置。type="com.qcby.entity.Student"
:指定了这个resultMap
映射到的Java类型,这里是com.qcby.entity.Student
类。- result标签:
- 这些标签用于定义数据库列到Java对象属性的直接映射。
- 例如,
<result property="id" column="id"/>
表示将数据库中的id
列映射到Student
对象的id
属性上。- 同样的,
Sname
、sex
、age
和t_id
列分别映射到Student
对象的Sname
、sex
、age
和t_id
属性上。- association标签:
<association property="teacher" javaType="com.qcby.entity.Teacher">
:这个标签用于处理复杂类型的属性映射,这里表示Student
对象中的teacher
属性(类型为Teacher
)的映射。- 在
association
内部,你可以定义Teacher
对象的属性映射。例如,<result property="id" column="id"/>
和<result property="Tname" column="Tname"/>
表示将数据库中的id
和Tname
列映射到Teacher
对象的id
和Tname
属性上。- 需要注意的是,这里的
id
列映射可能会有些混淆,因为在Student
和Teacher
的映射中都出现了。在实际应用中,可能需要通过别名(alias)来区分这两个id
列,确保它们正确地映射到各自的对象属性上。如下:<resultMap id="StudentTeacher1" type="com.qcby.entity.Student"> <id property="id" column="id"/> <result property="Sname" column="Sname"/> <result property="sex" column="sex"/> <result property="age" column="age"/> <result property="t_id" column="t_id"/> <!-- select="getTeacher" :调用下一个查询语句 --> <!-- column="t_id" 两个表的关联字段--> <association property="teacher" column="t_id" javaType="com.qcby.entity.Teacher" select="com.qcby.dao.TeacherDao.findTeacherById"/> </resultMap>
(3)Dao接口
List<Student> findStudentTeacher();
(4)Test类
@Test
public void findStudent(){
List<Student> student=mapper.findStudentTeacher();
for (Student s:student) {
System.out.println(s.toString());
}
}
(5)运行结果
2.第二种形式 分步查询
我们的目标是找到学生对应的老师:这个思路为先找到所有的老师,然后找到其所对应的学生
select * from student
select * from teacher where id = #{t_id};
(1)mapper层
StudentMapper.xml
<select id = "findStudentTeacher1" resultMap="StudentTeacher1">
select * from student;
</select>
<resultMap id="StudentTeacher1" type="com.qcby.entity.Student">
<id property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
<!-- select="getTeacher" :调用下一个查询语句 -->
<!-- column="t_id" 两个表的关联字段-->
<association property="teacher" column="t_id" javaType="com.qcby.entity.Teacher"
select="com.qcby.dao.TeacherDao.findTeacherById"/>
</resultMap>
TeacherMapper.xml
<select id="findTeacherById" resultType="com.qcby.entity.Teacher">
select * from teacher where id = #{t_id};
</select>
(2)Dao层
StudentDao
List<Student> findStudentTeacher1();
TeacherDao
Teacher findTeacherById();
(3)Test类
@Test
public void findStudent1(){
List<Student> student=mapper.findStudentTeacher1();
for (Student s:student) {
System.out.println(s.toString());
}
}
(4)运行结果
五、关联映射:一对多
查询每个老师有多少学生
1.第一种形式:按照结果嵌套处理
SELECT teacher.id,teacher.name,student.name FROM teacher
LEFT JOIN student on student.t_id = teacher.id
(1)设置实体类
学生类
这里需要将student类当中关于teacher的字段删除
private Integer id;
private String Sname;
private String sex;
private Integer age;
private Integer t_id;
教师类
因为要接收多个对象,这里用List<Student>
private Integer id;
private String Tname;
//这个一定要有
private List<Student> students;
(2)mapper层
<select id="TeacherStudent" resultMap="TeacherStudent">
SELECT student.*,teacher.* FROM student LEFT JOIN teacher on student.t_id = teacher.id
</select>
<resultMap id="TeacherStudent" type="com.qcby.entity.Teacher">
<result property="id" column="id"/>
<result property="Tname" column="Tname"/>
<collection property="students" ofType="com.qcby.entity.Student">
<result property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
</collection>
</resultMap>
复杂的属性我们需要单独去处理——resultMap中接收:对象:association 集合:collection。在集合中的泛型信息,我们使用ofType获取。
(3)Dao接口
List<Teacher> TeacherStudent();
(4)Test类
@Test
public void TeacherStudent(){
List<Teacher> teacher=mapper.TeacherStudent();
for (Teacher t:teacher) {
System.out.println(t.toString());
}
}
(5)运行结果
2.第二种形式:按照查询嵌套处理
(1).设置实体类
这里的实体类不需要变动
(2)mapper层
TeacherMapper.xml
<select id="TeacherStudent1" resultMap="TeacherStudent2">
select * from teacher
</select>
<resultMap id="TeacherStudent2" type="com.qcby.entity.Teacher">
<collection property="students" column="id" ofType="com.qcby.entity.Student"
select="com.qcby.dao.StudentDao.getStudentByTeacherId" />
</resultMap>
StudentMapper.xml
<select id="getStudentByTeacherId" resultType="com.qcby.entity.Student">
select * from student where t_id = #{t_id}
</select>
(3)Dao层
TeacherDao
List<Teacher> TeacherStudent1();
StudentDao
Student findStudentById();
(4)Test类
@Test
public void TeacherStudent1(){
List<Teacher> teacher=mapper.TeacherStudent1();
for (Teacher t:teacher) {
System.out.println(t.toString());
}
}
(5)运行结果
原文地址:https://blog.csdn.net/2301_78566776/article/details/144327424
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!