MyBatis的四十米大刀(高级映射)--个人与证件一对一关联查询(超详细解读)!!!

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。

而这里,我们来谈谈关联映射这个东西!!!
首先,我们来简略认知一下关联关系这个new thing。
在这里插入图片描述
在这里插入图片描述

其实,如果各位客官对于软件工程有点了解的话,对于关联关系就不陌生。为什么这么说呢?学过软件工程的就不得不会学点UML方面的知识,只不过UML更多的是关注模块之间的关系,而不像mybatis这样强调映射与对象。如果对于UML中常用关系感兴趣的话,可以参考这篇博客UML中常见关系详解(泛化、实现、依赖、关联、组合、聚合)

言归正传,咱们来进行关联查询的话题。
在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份,证,同时一个身份证也只会对应一个人。
在这里插入图片描述

那么使用MyBatis是怎么处理这种一对一关联关系的呢?

接下来用一个例子来解读。
既然是关于映射的问题,就不可避免的要提及数据库表格的结构。
在这里插入图片描述
填写的数据如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上面不难看出,数据表格之间的关联由外键来联系,而程序内部则是通过映射文件来实现对象与表格的一一对应关系。

1、在com.zsj.po包中创建持久化类ldCard和Person
IdCard.java

package com.zsj.po;
/**
 * 证件持久化类
 */
public class IdCard {
	private Integer id;
	private String code;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	@Override
	public String toString() {
		return "IdCard [id=" + id + ", code=" + code + "]";
	}
}

Person.java

package com.zsj.po;
/**
 * 个人持久化类
 */
public class Person {
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
	private IdCard card;  //个人关联的证件
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public IdCard getCard() {
		return card;
	}
	public void setCard(IdCard card) {
		this.card = card;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", "
				+ "age=" + age + ", sex=" + sex + ", card=" + card + "]";
	}
}

2、在com.zsj.mapper包中编写映射文件ldCardMapper xmI和PersonMapper xml
IdCardMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zsj.mapper.IdCardMapper">
  <!-- 根据id查询证件信息 -->
  <select id="findCodeById" parameterType="Integer" resultType="IdCard">
	  SELECT * from tb_idcard where id=#{id}
  </select>
</mapper>

说明:
●我们在映射文件中定义了一个 id 为findCardByld的statement, 输入参数类型为 Integer,输出参数类型为IdCard,此处resultType=“IdCard” 而没有 使用全路径resultType=“com.wz po.ldCard” ,是因为我们在配置文件mybatis config.xml中使用了别名
●这个statement完成的功能是根据证件id查询证件信息,返回结果的类型是IdCard

PersonMapper.xml(这里以嵌套查询为例,该解读的部分在后续博客中会更新的)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zsj.mapper.PersonMapper">
	<!-个人查询关联证件的resultMap定义:使用嵌套查询将整个查询的结果映射到Person中,分两步走:-:配置映射的个人信息
	第二步:配置嵌套查询,将查询结果映射到Person的card属性
	-->
	<!-- 嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
	<select id="findPersonById" parameterType="Integer" 
                                      resultMap="IdCardWithPersonResult">
		SELECT * from tb_person where id=#{id}
	</select>
	<resultMap type="Person" id="IdCardWithPersonResult">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="age" column="age" />
		<result property="sex" column="sex" />
		<!-- 一对一:association使用select属性引入另外一条SQL语句 -->
		<association property="card" column="card_id" javaType="IdCard"
			select="com.zsj.mapper.IdCardMapper.findCodeById" />
	</resultMap>
</mapper>

3、在核心配置文件mybatis-config xml中引入Mapper映射文件并定义别名

<?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>
	<properties resource="db.properties" />
	 <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="LOG4J" />
     	<!-- 打开延迟加载的开关 -->  
    	<setting name="lazyLoadingEnabled" value="true" />  
    	<!-- 将积极加载改为消息加载,即按需加载 -->  
    	<setting name="aggressiveLazyLoading" value="false"/>  
		</settings>
		<!--使用扫描包的形式定义别名 -->
		<typeAliases>
			<package name="com.zsj.po" />
		</typeAliases>
		<!--1.配置环境 ,默认的环境id为mysql -->
	<environments default="mysql">
		<!--1.2.配置id为mysql的数据库环境 -->
		<environment id="mysql">
			<!-- 使用JDBC的事务管理 -->
			<transactionManager type="JDBC" />
			<!--数据库连接池 -->
			<dataSource type="POOLED">
				<!-- 数据库驱动 -->
				<property name="driver" value="${jdbc.driver}" />
				<!-- 连接数据库的url -->
				<property name="url" value="${jdbc.url}" />
				<!-- 连接数据库的用户名 -->
				<property name="username" value="${jdbc.username}" />
				<!-- 连接数据库的密码 -->
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<!--2.配置Mapper的位置 -->
	<mappers>
	 	 <mapper resource="com/zsj/mapper/IdCardMapper.xml" />
         <mapper resource="com/zsj/mapper/PersonMapper.xml" />
	</mappers>
</configuration>

4、在test包中创建测试类MyBatisResultMapTest,编写测试方法findPersonByldTest

package test;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.zsj.po.Orders;
import com.zsj.po.Person;
import com.zsj.po.IdCard;
import com.zsj.po.User;
import com.zsj.utils.MyBatisUtils;
/**
 * Mybatis关联查询映射测试类
 */
public class MyBatisResultMapTest {
    /**
     * 嵌套查询
     */
    @Test
    public void findPersonByIdTest() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MyBatisUtils.getSession();
        // 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
        Person person = session.selectOne("com.zsj.mapper." 
                                   + "PersonMapper.findPersonById", 1);
        // 3、输出查询结果信息
        System.out.println(person);
        // 4、关闭SqlSession
        session.close();
    }
    

输出结果为:
在这里插入图片描述
输出结果的来源:在findPersonByldTest()方法中,首先通过MybatisUtils 工具类获取了SqlSession对象,然后通过SqlSession对象的selectOne()方法获取了个人信息。为了查看结果,这里使用了输出语句输出查询结果信息。最后程序执行完毕时,关闭了SqlSession。

虽然使用嵌套查询的方式比较简单,但是从输出结果图中可以看出,MyBatis嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大地消耗数据库性能并且会降低查询效率。这并不是开发人员所期望的。为此,我们可以使用MyBatis提供的嵌套结果方式,来进行关联查询。

嵌套结果方式的映射文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zsj.mapper.PersonMapper">
<!-- 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集 -->
	<select id="findPersonById2" parameterType="Integer" 
	                                   resultMap="IdCardWithPersonResult2">
	    SELECT p.*,idcard.code
	    from tb_person p,tb_idcard idcard
	    where p.card_id=idcard.id 
	    and p.id= #{id}
	</select>
	<resultMap type="Person" id="IdCardWithPersonResult2">
	    <id property="id" column="id" />
	    <result property="name" column="name" />
	    <result property="age" column="age" />
	    <result property="sex" column="sex" />
	    <association property="card" javaType="IdCard">
	        <id property="id" column="card_id" />
	        <result property="code" column="code" />
	    </association>
	</resultMap>	
</mapper>

想了解更多关于嵌套结果和嵌套查询的知识点,详情请见下篇博客=》》嵌套查询和嵌套结果的相爱相杀!!!

本文参考文献:
Mybatis官方文档之XML 映射器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值