Mybatis的关联映射案例
主要是对之前学习的关联映射做一个案例,自己动手实践一下,可以理解的更好一点。
开发环境
开发工具:idea
Java环境: jdk1.8.0_121
数据库:SQLServer
项目结构,里面包含了三种关联映射的文件,会分别进行测试:

完整的mybatis-config.xml文件,MybatisUtils工具类和db.properties文件
<?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="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为消息加载,即按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--使用扫描包创建别名-->
<typeAliases>
<package name="com.ma.po"/>
</typeAliases>
<!--配置环境,默认的环境id为sqlserver-->
<environments default="sqlserver">
<!--配置id为sqlserver的数据库环境-->
<environment id="sqlserver">
<!--使用JDBC的事务管理-->
<transactionManager type="JDBC"/>
<!--数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置mapper的位置-->
<mappers>
<mapper resource="com/ma/mapper/IdCardMapper.xml"/>
<mapper resource="com/ma/mapper/PersonMapper.xml"/>
<mapper resource="com/ma/mapper/UserMapper.xml"/>
<mapper resource="com/ma/mapper/OrdersMapper.xml"/>
<mapper resource="com/ma/mapper/ProductMapper.xml"/>
</mappers>
</configuration>
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
//初始化SqlSessionFactory对象
static {
try {
//使用M主Batis提供的Resources类加载MyBatis的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//构建SqlSessionFactory工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取SqlSession对象的静态方法
* @return
*/
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://localhost:1433;DatabaseName=mybatis
jdbc.username=
jdbc.password=
一对一案例(模拟人和身份证的关系)
1.创建两张数据表,tb_idcard和tb_person,并插入一些测试数据。
create table tb_idcard(
id int identity(1,1) PRIMARY key,
code varchar(18),
);
insert into tb_idcard values ('321321199403012967');
insert into tb_idcard values ('320321188505044526');
create table tb_person(
id int identity(1,1) PRIMARY key,
name varchar(32),
age int,
sex varchar(8),
card_id int UNIQUE,
FOREIGN KEY (card_id) REFERENCES tb_idcard(id)
);
insert into tb_person values ('Rose',29,'女',1);
insert into tb_person values ('tom',26,'男',2);
2.创建两个实体类:IdCard和Person
/**
* @author mz
* @version V1.0
* @Description: 证件持久化类
* @create 2017-11-02 10:12
*/
public class IdCard {
private Integer id;
private String code;
//省略setter和getter方法
}
/**
* @author mz
* @version V1.0
* @Description: 个人持久化类
* @create 2017-11-02 10:13
*/
public class Person {
private Integer id;
private String name;
private Integer age;
private String sex;
private IdCard card; //个人关联的证件
//省略setter和getter方法
}
3.创建IdCardMapper.xml映射文件和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.ma.mapper.IdCardMapper">
<!--根据id查询证件信息-->
<select id="findCodeById" parameterType="Integer" resultType="IdCard">
select * from tb_idcard where id = #{id}
</select>
</mapper>
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.ma.mapper.PersonMapper">
<resultMap id="IdCardWithPersonResult" type="Person">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
<!--一对一:association使用select属性引入别处一条语句-->
<association property="card" column="card_id" javaType="IdCard"
select="com.ma.mapper.IdCardMapper.findCodeById"/>
</resultMap>
<!--嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
<select id="findPersonById" parameterType="Integer" resultMap="IdCardWithPersonResult">
select * from tb_person where id = #{id}
</select>
<resultMap id="IdCardWithPersonResult2" type="Person">
<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>
<!--嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
<select id="findPersonById2" parameterType="Integer" resultMap="IdCardWithPersonResult2">
select p.*,c.code
from tb_person p,tb_idcard c
where p.card_id = c.id and p.id = #{id}
</select>
4.在测试类中添加测试方法
/**
* 嵌套查询
*/
@Test
public void findPersonByIdTest() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
//使用MyBatis嵌套查询的方式查询id为1的人的信息
Person person = sqlSession.selectOne("com.ma.mapper.PersonMapper.findPersonById",1);
//输出信息
System.out.println(person);
//关闭SqlSession
sqlSession.close();
}
/**
* 嵌套结果
*/
@Test
public void findPersonByIdTest2() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
//使用MyBatis嵌套查询的方式查询id为1的人的信息
Person person = sqlSession.selectOne("com.ma.mapper.PersonMapper.findPersonById2",1);
//输出信息
System.out.println(person);
//关闭SqlSession
sqlSession.close();
}
5.分别运行findPersonByIdTest()和findPersonByIdTest2()的结果如下:


从结果来看,嵌套查询要比嵌套结果多执行一条语句,结果是一样的。
一对多案例(模拟用户与订单的关系)
1.新建表tb_user和tb_orders
create table tb_user(
id int identity(1,1) PRIMARY key,
username varchar(32),
address varchar(256)
);
insert into tb_user values ('詹姆斯','克利夫兰');
insert into tb_user values ('科比','洛杉矶');
insert into tb_user values ('保罗','洛杉矶');
create table tb_orders(
id int identity(1,1) PRIMARY key,
number varchar(32) not null,
user_id int not null,
FOREIGN KEY (user_id) REFERENCES tb_user(id)
);
insert into tb_orders values ('1000011','1');
insert into tb_orders values ('1000012','2');
insert into tb_orders values ('1000013','3');
2.新建持久化类Orders和User。
public class Orders {
private Integer id; //订单id
private String number;//订单编号
private List<Product> products;//关联商品集合信息
//省略setter和getter方法
}
public class User {
private Integer id; //用户编号
private String username; //用户名
private String address; //用户地址
private List<Orders> ordersList;//用户关联的订单
//省略setter和getter方法
}
3.新建User|Mapper.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.ma.mapper.UserMapper">
<resultMap id="UserWithOrdersResult" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
<!--一对多关联映射:collection ofType表示属性集合中元素的类型,List<Orders>属性即Orders类-->
<collection property="ordersList" ofType="Orders">
<id property="id" column="orders_id"/>
<result property="number" column="number"/>
</collection>
</resultMap>
<!--一对多:查看某一用户及其关联的订单信息,注意:当关联查询出的列名相同,则需要使用别名区分-->
<select id="findUserWithOrders" parameterType="Integer" resultMap="UserWithOrdersResult">
select u.*,o.id as orders_id, o.number
from tb_user u, tb_orders o
where u.id = o.user_id
and u.id = #{id}
</select>
</mapper>
4.添加测试代码:
/**
* 一对多
*/
@Test
public void findUserTest() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
//查询id为1的人的信息
User user = sqlSession.selectOne("com.ma.mapper.UserMapper.findUserWithOrders",1);
//输出信息
System.out.println(user);
//关闭SqlSession
sqlSession.close();
}
5.测试结果:

多对多(模拟订单和商品的关系)
1.新建数据表tb_product和tb_ordersitem
create table tb_product(
id int identity(1,1) PRIMARY key,
name varchar(32),
price float
);
insert into tb_product values ('java','44.5');
insert into tb_product values ('java web','38.5');
insert into tb_product values ('ssm','50');
create table tb_ordersitem(
id int identity(1,1) PRIMARY key,
orders_id int,
product_id int,
FOREIGN KEY (orders_id) REFERENCES tb_orders(id),
FOREIGN KEY (product_id) REFERENCES tb_product(id)
);
insert into tb_ordersitem values ('1','1');
insert into tb_ordersitem values ('1','3');
insert into tb_ordersitem values ('3','3');
2.创建Product持久化类
public class Product {
private Integer id; //商品id
private String name; //商品名称
private double price; //商品单价
private List<Orders> orders;//与订单的关联属性
//省略setter和getter方法
}
3.创建OrdersMapper.xml和ProductMapper.xml的映射文件
OrdersMapper.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.ma.mapper.OrdersMapper">
<resultMap id="OrdersWithProductResult" type="Orders">
<id property="id" column="id"/>
<result property="number" column="number"/>
<collection property="products" column="id" ofType="Product" select="com.ma.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
<!--多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
<select id="findOrdersWithProduct" parameterType="Integer" resultMap="OrdersWithProductResult">
select * from tb_orders where id = #{id}
</select>
<resultMap id="OrdersWithProductResult2" type="Orders">
<id property="id" column="id"/>
<result property="number" column="number"/>
<collection property="products" ofType="Product">
<id property="id" column="pid"/>
<result property="name" column="name"/>
<result property="price" column="price"/>
</collection>
</resultMap>
<select id="findOrdersWithProduct2" parameterType="Integer" resultMap="OrdersWithProductResult2">
select o.*,p.id as pid,p.name,p.price
from tb_orders o,tb_product p,tb_ordersitem oi
where
oi.orders_id = o.id and oi.product_id = p.id and o.id = #{id}
</select>
</mapper>
ProductMapper.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.ma.mapper.ProductMapper">
<select id="findProductById" parameterType="Integer" resultType="Product">
select * from tb_product
where
id in(select product_id from tb_ordersitem where orders_id = #{id})
</select>
</mapper>
4.添加测试代码
/**
* 多对多
*/
@Test
public void findOrdersTest() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
//查询id为1的订单中的商品的信息
Orders orders = sqlSession.selectOne("com.ma.mapper.OrdersMapper.findOrdersWithProduct",1);
//输出信息
System.out.println(orders);
//关闭SqlSession
sqlSession.close();
}
/**
* 多对多
*/
@Test
public void findOrdersTest2() {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
//查询id为1的订单中的商品的信息
Orders orders = sqlSession.selectOne("com.ma.mapper.OrdersMapper.findOrdersWithProduct2",1);
//输出信息
System.out.println(orders);
//关闭SqlSession
sqlSession.close();
}
5.分别运行findOrdersTest()和findOrdersTest2()的运行结果


小结
以上是对Mybatis对关联关系处理的一个实践,代码测试没有问题。
Mybatis的关联映射案例的更多相关文章
- 04—mybatis的关联映射
mybatis的关联映射一对一一对多多对多 一.一对一(一个人只能有一个身份证号) 1.创建表创建表tb_card CREATE TABLE `tb_card` ( `id` int(11) NOT ...
- mybatis 一对一关联映射实例
在实际项目开发中,经常存在一对一的关系,如一个人对应一张身份证信息,这就是一对一的关系.下面是一个简单的实例: 1.建表过程我就省略了,主要是一张Person表,一张IDCard表,其相关属性见步骤2 ...
- mybatis之关联映射
###mybatis使用之一对一关联映射 1)分析并画ER图.(特别是一对一.一对多.多对多的情况) 2)启动终端数据库,并建库建表,在表中插入值和字段,并查看结果.(后期把navicat用上) 3) ...
- Mybatis的关联映射
实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系.针对多表之间的操作,MyBatis提供了关联映射, 通过关联映射就可以很好的处理对象与对象之间的关联关 ...
- MyBatis的关联映射和动态SQL
CREATE TABLE tb_card ( id INT PRIMARY KEY AUTO_INCREMENT, CODE ) ); '); CREATE TABLE tb_person ( id ...
- 【Hibernate框架】关联映射(一对一关联映射)
一.整理思路: 之前,小编总结过Mybatis的关联映射,接下来,再来总结一下hibernate的相关的关联映射,直接上图: 这张图,就是小编整理总结整个Hibernate的关联映射的一个大致思路. ...
- (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射
http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...
- Mybatis(四)关联映射
一. Mybatis关联映射 1 讲数据库中关联关系,主键表与外键表 一对多,多对一,主键表表示一 与外键表表示多 学生与学校的关系,工人与工厂,人员与部门的关系,.... 多 一 ...
- SSM框架开发web项目系列(三) MyBatis之resultMap及关联映射
前言 在上篇MyBatis基础篇中我们独立使用MyBatis构建了一个简单的数据库访问程序,可以实现单表的基本增删改查等操作,通过该实例我们可以初步了解MyBatis操作数据库需要的一些组成部分(配置 ...
随机推荐
- Linux 内核分析第八周学习笔记
Linux 内核分析第八周学习笔记 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10 ...
- ping: unknown host 解决办法
如果ping命令返回如下错误,那主要的可能性就是系统的DNS设置有误. [root@CentOS5 ~]# ping www.sina.com.cn ping: unknown host www.si ...
- 使图片水平并垂直居中的一个Hack
淘宝的一个前端面试题:使用纯CSS实现未知尺寸的图片(但高宽都小于200px)在200px的正方形容器中水平和垂直居中. 想起了vertical-align:middle;但是不行,后来才知道还要di ...
- [转载]js正则表达式语法
1. 正则表达式规则 1.1 普通字符 字母.数字.汉字.下划线.以及后边章节中没有特殊定义的标点符号,都是"普通字符".表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的 ...
- java中的null和""区别------&&与&的区别
(1)问题一:null和""的区别String s=null;string.trim()就会抛出为空的exception String s=""; string ...
- TC规则
633人阅读 TC规则涉及到 队列(QUEUE) 分类器(CLASS) 过滤器(FILTER),filter划分的标志位可用U32或iptables的set-mark来实现 ) 一般是" ...
- Node + vue 实现移动官网
简介 使用 Node + vue 对公司的官网进行了一个简单的移动端的实现. 源码 https://github.com/wx1993/node-vue-fabaocn 效果 组件 轮播图(使用 vu ...
- LightOJ 1088 - Points in Segments 二分
http://www.lightoj.com/volume_showproblem.php?problem=1088 题意:给出N个点,Q个查询,问在区间内的点数有多少个. 思路:直接在线二分,注意边 ...
- hadoop之存储篇
---持续更新中,可留言讨论--- --题目导航见页面左上角的悬浮框#目录导航#-- 一.目录: 集群规划 HDFS HA 冒烟测试 功能特性 二.集群规划: 负载类型 容量规划 可扩展性 角色分离 ...
- C.Fountains(Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2)+线段树+RMQ)
题目链接:http://codeforces.com/contest/799/problem/C 题目: 题意: 给你n种喷泉的价格和漂亮值,这n种喷泉题目指定用钻石或现金支付(分别用D和C表示),C ...