主要是对之前学习的关联映射做一个案例,自己动手实践一下,可以理解的更好一点。

开发环境

开发工具: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的关联映射案例的更多相关文章

  1. 04—mybatis的关联映射

    mybatis的关联映射一对一一对多多对多 一.一对一(一个人只能有一个身份证号) 1.创建表创建表tb_card CREATE TABLE `tb_card` ( `id` int(11) NOT ...

  2. mybatis 一对一关联映射实例

    在实际项目开发中,经常存在一对一的关系,如一个人对应一张身份证信息,这就是一对一的关系.下面是一个简单的实例: 1.建表过程我就省略了,主要是一张Person表,一张IDCard表,其相关属性见步骤2 ...

  3. mybatis之关联映射

    ###mybatis使用之一对一关联映射 1)分析并画ER图.(特别是一对一.一对多.多对多的情况) 2)启动终端数据库,并建库建表,在表中插入值和字段,并查看结果.(后期把navicat用上) 3) ...

  4. Mybatis的关联映射

    实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系.针对多表之间的操作,MyBatis提供了关联映射, 通过关联映射就可以很好的处理对象与对象之间的关联关 ...

  5. MyBatis的关联映射和动态SQL

    CREATE TABLE tb_card ( id INT PRIMARY KEY AUTO_INCREMENT, CODE ) ); '); CREATE TABLE tb_person ( id ...

  6. 【Hibernate框架】关联映射(一对一关联映射)

    一.整理思路: 之前,小编总结过Mybatis的关联映射,接下来,再来总结一下hibernate的相关的关联映射,直接上图: 这张图,就是小编整理总结整个Hibernate的关联映射的一个大致思路. ...

  7. (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射

    http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...

  8. Mybatis(四)关联映射

    一. Mybatis关联映射 1 讲数据库中关联关系,主键表与外键表 一对多,多对一,主键表表示一 与外键表表示多 学生与学校的关系,工人与工厂,人员与部门的关系,.... 多        一    ...

  9. SSM框架开发web项目系列(三) MyBatis之resultMap及关联映射

    前言 在上篇MyBatis基础篇中我们独立使用MyBatis构建了一个简单的数据库访问程序,可以实现单表的基本增删改查等操作,通过该实例我们可以初步了解MyBatis操作数据库需要的一些组成部分(配置 ...

随机推荐

  1. (转)C#中“EQUALS”与“==”的速度比较

    结论: true判断时,用"value" == string是最快的:false判断时,用"value".Equals(string)是最快的. 也就是说:一个 ...

  2. CSK & KCF(tracking)

    转自:http://blog.csdn.net/ben_ben_niao/article/details/51364323 上次介绍了SRDCF算法,发展历史轨迹为CSK=>>KCF/DC ...

  3. 浅谈cocosd之autorelease\retain\release的理解

    三种情况,引出问题:   1) new出来的对象需要释放,而释放时,如果有其他人引用了这个对象,再次使用这个对象时,则会出现野指针情况. ==> 于是出现了引用计数的释放管理机制. 2) 对于一 ...

  4. Codeforces Round #546 (Div. 2) ABCDE 题解

    1136A: 题意:一本书有n个章节,每个章节的分别在li到ri页,小明读完书后将书折在第k页,问还有多少章节没有读 题解:控制k在li~ri的范围内后输出n-i即可 #include <set ...

  5. 前端PHP入门-011-可变函数

    可变函数,我们也会称呼为变量函数.简单回顾一下之前的知识点: <?php $hello = 'world'; $world = '你好'; //输出的结果为:你好 echo $$hello; ? ...

  6. 跟我一起写Makefile(三)

    书写规则———— 规则包含两个部分,一个是依赖关系,一个是生成目标的方法. 在Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来 ...

  7. centos7 samba匿名访问设置

    [global] workgroup = WORKGROUP server string = Samba Server %v netbios name = centos security = user ...

  8. Linux 下 JDK + Eclipse + PyDev 安装与配置

    一:JDK / JRE 环境 Eclipse 是运行于Java虚拟机中的,所以必须先安装Java环境才能进行开发测试.JRE(Java Runtime Environment)是运行环境,JDK(Ja ...

  9. 计算方法 -- 解线性方程组直接法(LU分解、列主元高斯消元、追赶法)

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> ...

  10. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...