Mybatis入门(2)

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: 0
DEBUG [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种情况: 
  1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
  2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个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>












版权声明:本文为qq_20587295原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。