Mybatis入门(1)动态SQL
MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言,动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。MyBatis 3 以后精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
- bind
先讲一下#与$符号的区别:
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
2. $将传入的数据直接显示生成在sql中。#{}预编译完是占位符?,而${}预编译完就是传进来的参数。
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.
7.Mybatis使用order by 动态参数时需要注意,用$而不是#。
<!-- <if>元素使用 -->
<select id="findCustomerByNameAndJobs1" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer where 1=1
<if test="username !=null and username !=''">
and username like '%${username}%'
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</select><!-- <where>元素 -->
<select id="findCustomerByNameAndJobs2" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer
<where>
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</where>
</select>
<!-- <trim>元素 -->
<select id="findCustomerByNameAndJobs3" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer
<trim prefix="where" prefixOverrides="and">
<if test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</trim>
</select>上述两个元素的引入其实就是为了省略 select * from t_customer where 1=1 既避免SQL语句出错,又省去条件一直为真的情况。
if标签的test属性多用于条件判断语句,用于判别真假,如果条件为真,则进行动态SQL组装。下面来个运行实例:
1)输入条件为真(customer.setUsername("jack");)
DEBUG [main] - ==> Preparing: select * from t_customer where 1=1 and username like concat('%',?,'%')
DEBUG [main] - ==> Parameters: jack(String)
DEBUG [main] - <== Total: 1
Customer [id=2, username=jack, jobs=teacher, phone=12344565776]2)输入条件为假(注释掉上述代码)
DEBUG [main] - ==> Preparing: select * from t_customer where 1=1
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 4
Customer [id=1, username=joy, jobs=doctor, phone=13745874587]
Customer [id=2, username=jack, jobs=teacher, phone=12344565776]
Customer [id=3, username=tom, jobs=worker, phone=32141234151]
Customer [id=4, username=rose, jobs=student, phone=13333533092] <!--<choose>(<when>、<otherwise>)元素使用 -->
<select id="findCustomerByNameOrJobs" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>上述写法有一个问题需要注意,当前两个条件都不成立第三条一定会成立,会返回所有的数据。查询如下:注释掉一二句和不注释的区别。
customer.setUsername("zhangsan");
customer.setJobs("lisi");
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2a225dd7]
DEBUG [main] - ==> Preparing: select * from t_customer where 1=1 and username like concat('%',?, '%')
DEBUG [main] - ==> Parameters: zhangsan(String)
DEBUG [main] - <== Total: 0DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3e2059ae]
DEBUG [main] - ==> Preparing: select * from t_customer where 1=1 and phone is not null
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 4
Customer [id=1, username=joy, jobs=doctor, phone=13745874587]
Customer [id=2, username=jack, jobs=teacher, phone=12344565776]
Customer [id=3, username=tom, jobs=worker, phone=32141234151]
Customer [id=4, username=rose, jobs=student, phone=13333533092]set元素主要用于更新操作,其主要作用是在动态包含的SQL语句前输出一个set关键字,并将SQL语句中最后一个多余的逗号去掉 。使用它时,传入的字段不能为空。
<!-- <set>元素 -->
<update id="updateCustomer" parameterType="com.Mybatis.po.Customer">
update t_customer
<set>
<if test="username !=null and username !=''">
username=#{username},
</if>
<if test="jobs !=null and jobs !=''">
jobs=#{jobs},
</if>
<if test="phone !=null and phone !=''">
phone=#{phone},
</if>
</set>
where id=#{id}
</update>foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。 - item表示集合中每一个元素进行迭代时的别名;
- index指定一个名字,用于表示在迭代过程中,每次迭代到的位置;
- open表示该语句以什么开始;
- separator表示在每次进行迭代之间以什么符号作为分隔符;
- close表示以什么结束;
- collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有3种情况:
- 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
<!--<foreach>元素使用 -->
<select id="findCustomerByIds" parameterType="List"
resultType="com.Mybatis.po.Customer">
select * from t_customer where id in
<foreach item="id" index="index" collection="list" open="("separator="," close=")">
#{id}
</foreach>
</select>DEBUG [main] - ==> Preparing: select * from t_customer where id in ( ? , ? )
DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer)
DEBUG [main] - <== Total: 2
Customer [id=1, username=joy, jobs=doctor, phone=13745874587]
Customer [id=2, username=jack, jobs=teacher, phone=12344565776]bind元素主要用于解决多数据库的移植问题,使用mybatis自带的语言完成。
<!--<bind>元素的使用:根据客户名模糊查询客户信息 -->
<select id="findCustomerByName" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
<!--_parameter.getUsername()也可直接写成传入的字段属性名,即username -->
<bind name="pattern_username" value="'%'+_parameter.getUsername()+'%'" />
select * from t_customer
where
username like #{pattern_username}
</select>现在给出完整的示例代码:
1.配置文件
<?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" />
<!--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/Mybatis/mapper/CustomerDongtaiMapper.xml" />
</mappers>
</configuration>
2.映射文件
<?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.Mybatis.mapper.CustomerMapper">
<!-- <if>元素使用 -->
<select id="findCustomerByNameAndJobs1" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer where 1=1
<if test="username !=null and username !=''">
and username like '%${username}%'
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</select>
<!-- <where>元素 -->
<select id="findCustomerByNameAndJobs2" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer
<where>
<if test="username !=null and username !=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</where>
</select>
<!-- <trim>元素 -->
<select id="findCustomerByNameAndJobs3" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer
<trim prefix="where" prefixOverrides="and">
<if test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</if>
</trim>
</select>
<!--<choose>(<when>、<otherwise>)元素使用 -->
<select id="findCustomerByNameOrJobs" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
<!-- <set>元素 -->
<update id="updateCustomer" parameterType="com.Mybatis.po.Customer">
update t_customer
<set>
<if test="username !=null and username !=''">
username=#{username},
</if>
<if test="jobs !=null and jobs !=''">
jobs=#{jobs},
</if>
<if test="phone !=null and phone !=''">
phone=#{phone},
</if>
</set>
where id=#{id}
</update>
<!--<foreach>元素使用 -->
<select id="findCustomerByIds" parameterType="List"
resultType="com.Mybatis.po.Customer">
select * from t_customer where id in
<foreach item="id" index="index" collection="list" open="("
separator="," close=")">
#{id}
</foreach>
</select>
<!--<bind>元素的使用:根据客户名模糊查询客户信息 -->
<select id="findCustomerByName" parameterType="com.Mybatis.po.Customer"
resultType="com.Mybatis.po.Customer">
<!--_parameter.getUsername()也可直接写成传入的字段属性名,即username -->
<bind name="pattern_username" value="'%'+_parameter.getUsername()+'%'" />
select * from t_customer
where
username like #{pattern_username}
</select>
</mapper>
Java文件,其他代码参见Mybatis入门(1)
package com.Mybatis.junitTest;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.Mybatis.po.Customer;
import com.Mybatis.utils.MybatisUtils;
public class MybatisDongtaiTest {
/**
* 根据客户姓名和职业组合条件查询客户信息列表
*/
@Test
public void findCustomerByNameAndJobsTest(){
// 通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 创建Customer对象,封装需要组合查询的条件
Customer customer = new Customer();
//customer.setUsername("jack");
// customer.setJobs("teacher");
// 执行SqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.Mybatis.mapper"
+ ".CustomerMapper.findCustomerByNameAndJobs1",customer);
// 输出查询结果信息
for (Customer customer2 : customers) {
// 打印输出结果
System.out.println(customer2);
}
// 关闭SqlSession
session.close();
}
/**
* 根据客户姓名或职业查询客户信息列表
*/
@Test
public void findCustomerByNameOrJobsTest(){
// 通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 创建Customer对象,封装需要组合查询的条件
Customer customer = new Customer();
// customer.setUsername("zhangsan");
//customer.setJobs("lisi");
customer.setPhone("12345678901");
// 执行SqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.Mybatis.mapper"
+ ".CustomerMapper.findCustomerByNameOrJobs",customer);
// 输出查询结果信息
for (Customer customer2 : customers) {
// 打印输出结果
System.out.println(customer2);
}
// 关闭SqlSession
session.close();
}
/**
* 更新客户
*/
@Test
public void updateCustomerTest() {
// 获取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
// 创建Customer对象,并向对象中添加数据
Customer customer = new Customer();
customer.setId(3);
customer.setPhone("13311111234");
// 执行SqlSession的更新方法,返回的是SQL语句影响的行数
int rows = sqlSession.update("com.Mybatis.mapper"
+ ".CustomerMapper.updateCustomer", customer);
// 通过返回结果判断更新操作是否执行成功
if(rows > 0){
System.out.println("您成功修改了"+rows+"条数据!");
}else{
System.out.println("执行修改操作失败!!!");
}
// 提交事务
sqlSession.commit();
// 关闭SqlSession
sqlSession.close();
}
/**
* 根据客户编号批量查询客户信息
*/
@Test
public void findCustomerByIdsTest(){
// 获取SqlSession
SqlSession session = MybatisUtils.getSession();
// 创建List集合,封装查询id
List<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(2);
// 执行SqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.Mybatis.mapper"
+ ".CustomerMapper.findCustomerByIds", ids);
// 输出查询结果信息
for (Customer customer : customers) {
// 打印输出结果
System.out.println(customer);
}
// 关闭SqlSession
session.close();
}
/**
* bind元素的使用:根据客户名模糊查询客户信息
*/
@Test
public void findCustomerByNameTest(){
// 通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 创建Customer对象,封装查询的条件
Customer customer =new Customer();
customer.setUsername("j");
// 执行sqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.Mybatis.mapper"
+ ".CustomerMapper.findCustomerByName", customer);
// 输出查询结果信息
for (Customer customer2 : customers) {
// 打印输出结果
System.out.println(customer2);
}
// 关闭SqlSession
session.close();
}
}
关联映射(多表操作)
在这不介绍关系数据库模型,具体内容可以参见萨师煊的《数据库系统概论》,详略得当,很经典。
一对一可以描述为:
class A{
B b;
}
class B {
A a;
}
一对多的关系:
class A{
List<B> b;
}
class B{
A a;
}
多对多的关系:
class A{
List<B> b;
}
class B{
List<A> a;
}
一对一关系的实现:
association元素来实现一对一的关系,其中还有property元素,指定映射到实体对象的属性,column指定表中对应的字段,Javatype指定映射到实体对象属性的类型,select元素能够引入嵌套查询的子SQL语句,fetchtype指定关联查询时是否启用延迟加载,他有lazy和eager两种属性。Mybatis在映射文件中加载关联文件对象有两种方式,嵌套查询和嵌套结果,前者是指通过另一条Sql映射语句来返回预期的复杂类型,后者是使用嵌套结果映射来处理重复的联合结果的子集。配置方式如下:
<!-- 一对一:association使用select属性引入另外一条SQL语句 -->
<association property="card" column="card_id" javaType="IdCard"
select="com.Mybatis.mapper.IdCardMapper.findCodeById" /> <association property="card" javaType="IdCard">
<id property="id" column="card_id" />
<result property="code" column="code" />
</association>测试结果如下:可见第二种方式查询效率更高,对于大型数据查询更有效。
DEBUG [main] - ==> Preparing: SELECT * from tb_person where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: SELECT * from tb_idcard where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
Person [id=1, name=Rose, age=29, sex=女, card=IdCard [id=1, code=152221198711020624]]DEBUG [main] - ==> Preparing: SELECT p.*,idcard.code from tb_person p,tb_idcard idcard where p.card_id=idcard.id and p.id= ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
Person [id=1, name=Rose, age=29, sex=女, card=IdCard [id=1, code=152221198711020624]]<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 将积极加载改为消息加载,即按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>在使用关联映射查询时,可以采用上述配置,提高查询效率,该设置是开启延迟加载。上述测试完整代码如下:
package com.Mybatis.po;
/**
* 个人持久化类person.java
*/
public class Person {
private Integer id;
private String name;
private Integer age;
private String sex;
private IdCard card; //个人关联的证jian
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 + "]";
}
}
package com.Mybatis.po;
/**
* 证件持久化类IdCard */
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 + "]";
}
}
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.Mybatis.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.Mybatis.mapper.PersonMapper">
<!-- 嵌套查询:通过执行另外一条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.Mybatis.mapper.IdCardMapper.findCodeById" />
</resultMap>
<!-- 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集 -->
<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>
@Test
public void findPersonByIdTest() {
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
Person person = session.selectOne("com.Mybatis.mapper."
+ "PersonMapper.findPersonById", 1);
// 3、输出查询结果信息
System.out.println(person);
// 4、关闭SqlSession
session.close();
}
@Test
public void findPersonByIdTest2() {
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套结果的方法查询id为1的人的信息
Person person = session.selectOne("com.Mybatis.mapper."
+ "PersonMapper.findPersonById2", 1);
// 3、输出查询结果信息
System.out.println(person);
// 4、关闭SqlSession
session.close();
}<?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.Mybatis.po" />
</typeAliases>
<!--配置环境 ,默认的环境id为mysql -->
<environments default="mysql">
<!-- 配置id为mysql的数据库环境 -->
<environment id="mysql">
<!-- 使用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/Mybatis/mapper/IdCardMapper.xml" />
<mapper resource="com/Mybatis/mapper/PersonMapper.xml" />
</mappers>
</configuration>
下面的程序配置方法类似,不再给出,如果不明白可以参考前面的教程。
一对多关系的实现:collection元素用来处理一对多的关系,其用法类似于association,但是其中包括一个特殊元素ofType,对应于java属性,用于指定实体对象中集合类属性所包含的元素类型。两种参考配置方式如下:
DEBUG [main] - ==> Preparing: 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=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 2
User [id=1, username=詹姆斯, address=哈哈哈哈哈哈, ordersList=[Orders [id=1, number=1000011, productList=null], Orders [id=2, number=1000012, productList=null]]]多对多的实现:
package com.Mybatis.test;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.Mybatis.po.Orders;
import com.Mybatis.po.Person;
import com.Mybatis.po.User;
import com.Mybatis.utils.MybatisUtils;
/**
* Mybatis关联查询映射测试类
*/
public class MybatisAssociatedTest {
/**
* 嵌套查询
*/
@Test
public void findPersonByIdTest() {
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
Person person = session.selectOne("com.Mybatis.mapper."
+ "PersonMapper.findPersonById", 1);
// 3、输出查询结果信息
System.out.println(person);
// 4、关闭SqlSession
session.close();
}
/**
* 嵌套结果
*/
@Test
public void findPersonByIdTest2() {
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套结果的方法查询id为1的人的信息
Person person = session.selectOne("com.Mybatis.mapper."
+ "PersonMapper.findPersonById2", 1);
// 3、输出查询结果信息
System.out.println(person);
// 4、关闭SqlSession
session.close();
}
/**
* 一对多
*/
@Test
public void findUserTest() {
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2、查询id为1的用户信息
User user = session.selectOne("com.Mybatis.mapper."
+ "UserMapper.findUserWithOrders", 1);
// 3、输出查询结果信息
System.out.println(user);
// 4、关闭SqlSession
session.close();
}
/**
* 多对多
*/
@Test
public void findOrdersTest(){
// 1、通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 2、查询id为1的订单中的商品信息
Orders orders = session.selectOne("com.Mybatis.mapper."
+ "OrdersMapper.findOrdersWithPorduct", 1);
// 3、输出查询结果信息
System.out.println(orders);
// 4、关闭SqlSession
session.close();
}
}
<?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.Mybatis.mapper.OrdersMapper">
<!-- 多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
<select id="findOrdersWithPorduct" parameterType="Integer"
resultMap="OrdersWithProductResult">
select * from tb_orders WHERE id=#{id}
</select>
<resultMap type="Orders" id="OrdersWithProductResult">
<id property="id" column="id" />
<result property="number" column="number" />
<collection property="productList" column="id" ofType="Product"
select="com.Mybatis.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
<!-- 多对多嵌套结果查询:查询某订单及其关联的商品详情 -->
<select id="findOrdersWithPorduct2" parameterType="Integer"
resultMap="OrdersWithPorductResult2">
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>
<!-- 自定义手动映射类型 -->
<resultMap type="Orders" id="OrdersWithPorductResult2">
<id property="id" column="id" />
<result property="number" column="number" />
<!-- 多对多关联映射:collection -->
<collection property="productList" ofType="Product">
<id property="id" column="pid" />
<result property="name" column="name" />
<result property="price" column="price" />
</collection>
</resultMap>
</mapper>
<?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.Mybatis.mapper.OrdersMapper">
<!-- 多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
<select id="findOrdersWithPorduct" parameterType="Integer"
resultMap="OrdersWithProductResult">
select * from tb_orders WHERE id=#{id}
</select>
<resultMap type="Orders" id="OrdersWithProductResult">
<id property="id" column="id" />
<result property="number" column="number" />
<collection property="productList" column="id" ofType="Product"
select="com.Mybatis.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
<!-- 多对多嵌套结果查询:查询某订单及其关联的商品详情 -->
<select id="findOrdersWithPorduct2" parameterType="Integer"
resultMap="OrdersWithPorductResult2">
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>
<!-- 自定义手动映射类型 -->
<resultMap type="Orders" id="OrdersWithPorductResult2">
<id property="id" column="id" />
<result property="number" column="number" />
<!-- 多对多关联映射:collection -->
<collection property="productList" ofType="Product">
<id property="id" column="pid" />
<result property="name" column="name" />
<result property="price" column="price" />
</collection>
</resultMap>
</mapper>