MyBatis关联映射

关联映射关系

我们拿学生和年级的关系来举例:
在这里插入图片描述

一对一:因为一个学生只能属于一个年级,所以从学生的角度一个学生只能对一个年级,一对一关系(实际上从模块的角度出发,多个学生同属一个年级,应该是多对一的关系,但是此处我们要从实际操作查询的角度出发,如果此处把他们看多多对一去查询就没有意义了)。
一对多:一个年级可以有多个学生,所有从年级的角度是一对多关系。


案例准备

1)在数据库中新建student和grade并添加数据
#先进grade
CREATE TABLE `NewTable` (
`grade_id`  int(4) NOT NULL AUTO_INCREMENT ,
`name`  varchar(7) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
PRIMARY KEY (`grade_id`)
)ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci;

#添加数据
INSERT INTO `mybatis`.`grade` (`grade_id`, `name`) VALUES ('1', '大一');
INSERT INTO `mybatis`.`grade` (`grade_id`, `name`) VALUES ('2', '大二');
INSERT INTO `mybatis`.`grade` (`grade_id`, `name`) VALUES ('3', '大三');


#新建student
CREATE TABLE `NewTable` (
`student_id`  int(4) NOT NULL AUTO_INCREMENT ,
`name`  varchar(7) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`age`  int(3) NULL DEFAULT NULL ,
`grade_id`  int(4) NOT NULL ,
PRIMARY KEY (`student_id`),
FOREIGN KEY (`grade_id`) REFERENCES `grade` (`grade_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `grade_id` (`grade_id`) USING BTREE 
)ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci;

#添加数据
INSERT INTO `mybatis`.`student` (`student_id`, `name`, `age`, `grade_id`) VALUES ('1', '张三', NULL, '1');
INSERT INTO `mybatis`.`student` (`student_id`, `name`, `age`, `grade_id`) VALUES ('2', '李四', NULL, '2');
INSERT INTO `mybatis`.`student` (`student_id`, `name`, `age`, `grade_id`) VALUES ('3', '王五', NULL, '1');
INSERT INTO `mybatis`.`student` (`student_id`, `name`, `age`, `grade_id`) VALUES ('4', '赵六', NULL, '3');

2)新建项目mybatis_demo03,搭建项目环境

导入jar包,db.properties,log4j.properties和SqlMapConfig.xml(不会的同学翻我前两章文章)
在这里插入图片描述

首先在SqlMapConfig.xml中配置好

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>	
	
	<!-- db.properties配置文件 -->
	<properties resource="db.properties"/>
	
    <!-- 和spring整合后environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${user}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
</configuration>
3)在com.oak.po中新建两个pojo类Student和Grade
public class Student {
	private Integer StudentId;
	private String name;
	private Integer age;
	private Integer gradeId;
	//方法略	
}
public class Grade {
	private Integer gradeId;
	private String name;
	//方法略
}

一对一关联映射

需求:查询所有学员信息,关联查询所属年级信息

方法一

使用resultType,定义学生信息PO类,此PO类中包括了学生信息和年级信息。在po包下新建一个StudentGrade类,让此类继承自Student类,然后添加Grade类的信息字段即可:

public class StudentGrade extends Student{
	private String gradeName;
	//方法略
}

注意:此处定义该类与vo的含义类似
按照需求,在com.oak.mapper包中新建StudentMapper接口,然后定义查询方法:

public interface StudentMapper {
	/**
	 * 查询所有学生信息--包括所属年级
	 * @return
	 */
	List<StudentGrade> findAll();
}

接在在同包下新建UserMapper.xml,在映射文件中添加select元素

<!-- 查询所有学生信息 -->
<select id="findAll" resultType="com.oak.po.StudentGrade">
	select stu.student_id studentId
	,stu.name name
	,stu.age
	,stu.grade_id gradeId
	,gra.name gradeName 
	from `student` stu left join `grade` gra on stu.grade_id=gra.grade_id
</select>

在SqlMapConfig.xml中加载映射文件:

<!-- 加载mapper映射文件 -->
<mappers>
	<package name="com.oak.mapper"/>
</mappers>

测试类中测试:

public class StuTest {	
	// 工厂对象一般在我们的系统中是单例的
	private SqlSessionFactory sqlSessionFactory=null;
	@Before
	public void init() throws IOException{
		// 第一步,创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 第二步,加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 第三步,创建SqlSessionFactory对象
        sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
	}
	@Test
	public void testFindAll(){
		SqlSession sqlSession=sqlSessionFactory.openSession();
		StudentMapper stuMapper=sqlSession.getMapper(StudentMapper.class);
		List<StudentGrade> stus=stuMapper.findAll();
		System.out.println(stus);
	}
}

查看结果:
在这里插入图片描述
小结:定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍,类似于vo。

方法二

使用resultMap,定义resultMap用于映射一对一查询结果。
首先在学生类中添加一个grade属性,grade属性用于存储关联查询的年级信息,因为学生关联年级是一对一,所以这里使用单个Grade对象来存储关联信息

public class Student {
	private Integer StudentId;
	private String name;
	private Integer age;
	private Integer gradeId;
	private Grade grade;
	//添加getter和setter方法
}

在UserMapper接口中定义方法findStuResutlMap:

/**
 * 查询所有的学生信息,使用resultMap封装关联信息
 * @return
 */
List<Student> findStuResultMap();

在UserMapper.xml中编写sql:

<select id="findStuResultMap" resultMap="student_grade_resultmap">
		select stu.student_id 
		,stu.name 
		,stu.age
		,stu.grade_id 
		,gra.name gname
		from `student` stu left join `grade` gra on stu.grade_id=gra.grade_id
</select>

定义id为student_grade_resultmap的ResultMap:

<resultMap type="student" id="student_grade_resultmap">
	<id property="studentId" column="student_id"/>
	<result property="name" column="name"/>
	<result property="age" column="age"/>
	<result property="gradeId" column="grade_id"/>
	 <!-- 配置一对一关联映射 -->
    <association property="grade" javaType="grade">
        <id property="gradeId" column="grade_id"/>
        <!-- 因为查询结果列名中有重名的name 所以起个别名用于区分 -->
        <result property="name" column="gname"/>
    </association>
</resultMap>
  • association:表示进行关联查询单条记录。

  • property:表示关联查询的结果存储在student的grade属性中。即 property对应Grade类里面一对一关联映射的那个属性,即grade属性。

  • javaType:表示关联查询的结果类型。即grade属性的数据类型,可使用别名。

  • < id property=“id” column=“grade_id”/>:查询结果的grade_id列对应关联对象的id属性,这里是表示grade_id是关联查询对象的唯一标识。

  • < result property=“name” column=“gname”/>:查询结果的gname列对应关联对象的name属性。

测试:

@Test
public void testFindAll(){
	SqlSession sqlSession=sqlSessionFactory.openSession();
	StudentMapper stuMapper=sqlSession.getMapper(StudentMapper.class);
	List<Student> stus=stuMapper.findStuResultMap();
	System.out.println(stus);
}

一对多关联映射

需求:查询所有年级,关联查询所有学生信息
类似于上面在在Student中加入一个Grade对象,因为一个Student对应一个Grade,是一对一关系。那么在此,一个年级对应多个学生,是一对多关系,所以在Grade中加入一个Student集合作为属性:

public class Grade {
	private Integer gradeId;
	private String name;
	private List<Student> students;
	//添加getter和setter方法
}

在新建GradeMapper接口,并定义查询方法:

/**
 * 查询所有年级信息--关联学生信息
 * @return
 */
List<Grade> findAll();

在同包中新建GradeMapper.xml映射文件

<select id="findStuResultMap" resultMap="grade_student_resultmap">
	select g.grade_id
	,g.name 
	,s.student_id
	,s.name sname
	,s.age 
	from `grade` g left join `student` s on g.grade_id=s.grade_id
</select>
<!--指定映射resultMap-->
<resultMap type="grade" id="grade_student_resultmap">
	<id property="gradeId" column="grade_id"/>
	<result property="name" column="name"/>
	 <!-- 配置一对一关联映射 -->
    <collection property="students" ofType="student">
        <id property="studentId" column="student_id"/>
        <!-- 因为查询结果列名中有重名的name 所以起个别名用于区分 -->
        <result property="name" column="sname"/>
        <result property="age" column="age"/>
		<result property="gradeId" column="grade_id"/>
    </collection>
</resultMap>

这里resultMap指定为grade_student_resultmap。

  • collection部分年级关联的学生信息,表示关联查询结果集。

  • property=”students”:关联查询的结果集存储在Grade对象的哪个属性上。即property对应Grade对象中的集合属性。

  • ofType=”student”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。

  • < id />及< result/>的意义同一对一查询。

测试:

@Test
public void testGradeFindAll(){
	SqlSession sqlSession=sqlSessionFactory.openSession();
	GradeMapper graMapper=sqlSession.getMapper(GradeMapper.class);
	List<Grade> grades=graMapper.findAll();
	System.out.println(grades);
}
  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

robona

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值