MyBatis 之 使用四(二) (mapper.xml)

执行查询操作的时候,通常返回的结果集会出现一下几种情况:

1. 一对一查询:返回的结果集的唯一主键是非重复的。(下面会标出唯一主键,和 oracle 的主键有区别)

查询订单以及订单的用户信息,两种接收结果集的方式:

1)使用 pojo 对象去接收结果集(唯一主键:)

public class OrderCustom extends User {
	private int orderId; //订单id
	private int user_id; //用户id
	private String orderNumber; //订单号
	public int getOrderId() {
		return orderId;
	}
	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}
	public int getUser_id() {
		return user_id;
	}
	public void setUser_id(int user_id) {
		this.user_id = user_id;
	}
	public String getOrderNumber() {
		return orderNumber;
	}
	public void setOrderNumber(String orderNumber) {
		this.orderNumber = orderNumber;
	}
	@Override
	public String toString() {
		String userString = super.toString();
		return "OrderCustom {orderId=" + orderId + ", user_id=" + user_id
				+ ", orderNumber=" + orderNumber + "[" + userString + "]" + "}";
	}

}
<!-- 查询订单及用户信息,resultType -->
  <select databaseId="oracle" id="findOrdersUsers_resultType" resultType="orderCustom">
  	select orders.*, users.* from orders, users where orders.user_id = users.userid
  </select>
public class OrderMapperTest extends TestCase {

	private SqlSessionFactory sqlSessionFactory;

	private String resource = "SqlMapConfig.xml";

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		//通过输入流读取配置文件
		InputStream inputStream = Resources.getResourceAsStream(resource);
		//获取SqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "development_oracle");
	}

	//一对一查询,使用resultType
	@Test
	public void testFindOrdersUsers_resultType() throws Exception {
		//获取SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		//指定 mapper 接口的类型,MyBatis通过动态代理的方式实现mapper接口
		OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);

		List<OrderCustom> list = orderMapper.findOrdersUsers_resultType();
		System.out.println(list.size());

		Iterator<OrderCustom> iterator = list.iterator();
		while (iterator.hasNext()) {
			OrderCustom orderCustom = (OrderCustom) iterator.next();
			System.out.println(orderCustom);
		}
	}
}

执行结果:

2)使用resultMap接收结果集

public class Order {
	private int orderId; //订单id
	private int user_id; //用户id
	private String orderNumber; //订单号

	private User user; //用户信息
	private List<OrderDetail> orderDetails;  //订单明细

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public int getUser_id() {
		return user_id;
	}

	public void setUser_id(int user_id) {
		this.user_id = user_id;
	}

	public String getOrderNumber() {
		return orderNumber;
	}

	public void setOrderNumber(String orderNumber) {
		this.orderNumber = orderNumber;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public List<OrderDetail> getOrderDetails() {
		return orderDetails;
	}

	public void setOrderDetails(List<OrderDetail> orderDetails) {
		this.orderDetails = orderDetails;
	}

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", user_id=" + user_id
				+ ", orderNumber=" + orderNumber + ", user=" + user
				+ ", orderDetails=" + orderDetails + "]";
	}
}
<!-- 查询订单及用户信息,resultMap -->
<resultMap id="orderUserMap" type="mybatis_b.model.Order">
  <!-- order信息 -->
  <!-- 这里的id 是mybatis在进行一对一查询时,将orderId字段映射为Order 对象使用,必须写 -->
  <id property="orderId" column="orderId"/>
  <result property="user_id" column="user_id"/>
  <result property="orderNumber" column="orderNumber"/>
  <!-- 用户信息 -->
  <!-- 将用户信息 使用 association 封装成一个user对象-->
  <!-- association:用于一对一查询,将查询出来的以下字段映射到单个对象
      property="user" : 指定封装对象存储的属性在orders中
      javaType : 指定属性的javaType
      user.username, user.sex, user.address
  -->
  <association property="user" javaType="mybatis_b.model.User">
  <!-- 这里的id为user的id,如果写表示给user的id属性赋值 -->
      <id property="userId" column="userId"/>
      <result property="username" column="username"/>
      <result property="sex" column="sex"/>
      <result property="birthday" column="birthday"/>
      <result property="address" column="address"/>
      <result property="detail" column="detail"/>
      <result property="score" column="score"/>
  </association>
</resultMap>
  
<select id="findOrdersUsers_resultMap" resultMap="orderUserMap">
    select orders.*, users.* from orders, users where orders.user_id = users.userid
</select>

java调用代码同上,只需修改

List<OrderCustom> list = orderMapper.findOrdersUsers_resultMap();

2.  一对多查询:返回的结果集的唯一主键是非重复的。如下:

查询订单以及订单明细信息,可以看出记录中存在 两个订单明细是属于同一个订单的 情况,这就是一对多的查询结果集。结果集有5条记录,但是应该只存在四个OrderId(因为两个重复的)。

一对多查询结果需要使用 resultMap 来接收,代码如下:

<!-- 订单及明细信息 -->
<resultMap id="orderDetails" type="mybatis_b.model.Order">
      <!-- id 这里表示结果集的唯一主键,虽然出现重复的orderDetail,但是属于同一个orderId -->
      <id property="orderId" column="orderId"/>
      <result property="user_id" column="user_id"/>
      <result property="orderNumber" column="orderNumber"/>
      <!-- collect:用于一对多查询,接收 List<object> 对象; ofType表示 List 中对象的类型 -->
      <!-- 上面 Order 类中的List<OrderDetail> 就是用来接收一对多的结果集 -->
      <collection property="orderDetails" ofType="mybatis_b.model.OrderDetail">
  	    <id property="orderDetailId" column="orderDetailId"/>
  	    <result property="item_id" column="item_id"/>
  	    <result property="item_number" column="item_number"/>
  	    <result property="item_price" column="item_price"/>
      </collection>
</resultMap>

<select id="findOrderDetails" resultMap="orderDetails">
  select orders.*, orderDetail.orderDetailId, orderDetail.item_id, 
  orderDetail.item_number, orderDetail.item_price from orders, orderDetail 
  where orders.orderId = orderDetail.order_id
</select>

OrderDetail 类:

public class OrderDetail {
	private int orderDetailId;  //order明细id
	private int order_id;	//订单id
	private int item_id;	//商品id
	private int item_number;	//商品数量
	private Float item_price;	//单价

	public int getOrderDetailId() {
		return orderDetailId;
	}
	public void setOrderDetailId(int orderDetailId) {
		this.orderDetailId = orderDetailId;
	}
	public int getOrder_id() {
		return order_id;
	}
	public void setOrder_id(int order_id) {
		this.order_id = order_id;
	}
	public int getItem_id() {
		return item_id;
	}
	public void setItem_id(int item_id) {
		this.item_id = item_id;
	}
	public int getItem_number() {
		return item_number;
	}
	public void setItem_number(int item_number) {
		this.item_number = item_number;
	}
	public Float getItem_price() {
		return item_price;
	}
	public void setItem_price(Float item_price) {
		this.item_price = item_price;
	}
	@Override
	public String toString() {
		return "OrderDetail [orderDetailId=" + orderDetailId + ", order_id="
				+ order_id + ", item_id=" + item_id + ", item_number="
				+ item_number + ", item_price=" + item_price + "]";
	}
}

java调用代码同上,只需修改

List<OrderCustom> list = orderMapper.findOrderDetails();

执行结果:可以看出,第二条order信息中,有两条 orderDetail 信息

3.  resultMap 继承

MyBatis 的 mapper.xml 配置文件中可以使用 resultMap 的继承。如下:

查询订单、订单明细以及订单的用户信息。上面我们已经有 orderUserMap 这个resultMap 来接收 订单以及用户信息了。下面继承这个 resultMap:

<!-- 订单、订单明细及用户信息 -->
<resultMap id="orderDetailsAndUser" type="mybatis_b.model.Order" extends="orderUserMap">
  <collection property="orderDetails" ofType="mybatis_b.model.OrderDetail">
  	<id property="orderDetailId" column="orderDetailId"/>
  	<result property="item_id" column="item_id"/>
  	<result property="item_number" column="item_number"/>
  	<result property="item_price" column="item_price"/>
  </collection>
</resultMap>
  
<select id="findOrderDetailsAndUser" resultMap="orderDetailsAndUser">
  select orders.*,users.*, orderDetail.orderDetailId, orderDetail.item_id, 
  orderDetail.item_number, orderDetail.item_price from orders, users, orderDetail 
  where orders.user_id = users.userid and orders.orderId = orderDetail.order_id
</select>

代码中 orderDetailsAndUser 这个 resultMap 继承了 orderUserMap, 所以 order 和 user 属性配置可以省略,减少代码量。

时间: 2024-10-13 16:58:55

MyBatis 之 使用四(二) (mapper.xml)的相关文章

mybatis自动生成dao, model, mapper xml文件

用mybatis的时候,手写xml或model文件是一个力气活,所以可以用mybatis-gennerator插件自动生成mybatis所需要的dao.bean.mapper xml文件 (原文地址:http://blog.csdn.net/tolcf/article/details/50835165) 附件下载地址:http://files.cnblogs.com/files/cc-robot/generator.rar 把附件解压到本地,我放在d:\web\java目录下了 只需要修改下面x

spring mybatis 整合问题Error parsing Mapper XML. Cause: java.lang.NullPointerException

14:30:40,872 DEBUG SqlSessionFactoryBean:431 - Parsed configuration file: 'class path resource [mybatis/mybatis-config.xml]'14:30:40,883  WARN XmlWebApplicationContext:489 - Exception encountered during context initialization - cancelling refresh att

Mybatis 源码解析(二) - Configuration.xml解析

文章个人学习源码所得,若存在不足或者错误之处,请大家指出. 上一章中叙述了Configuration.xml流化到Mybatis内存中的过程,那么接下来肯定就是Configuration.xml文件解析操作,在Mybatis中,这个解析的操作由SqlSesssionFactoryBuilder负责.接下来我们看看SqlSessionFactoryBuilder的方法签名: SqlSessionFactoryBuilder提供了9个签名方法,其中前8个方法都是Configuration.xml的解

mybatis如何通过接口查找对应的mapper.xml及方法执行详解

转:http://www.jb51.net/article/116402.htm 本文主要介绍的是关于mybatis通过接口查找对应mapper.xml及方法执行的相关内容,下面话不多说,来看看详细的介绍: 在使用mybatis的时候,有一种方式是 ? 1 BookMapper bookMapper = SqlSession().getMapper(BookMapper.class) 获取接口,然后调用接口的方法.只要方法名和对应的mapper.xml中的id名字相同,就可以执行sql. 那么接

MyBatis 之 使用四(一) (mapper.xml)

mapper.xml 映射文件是 MyBatis 的核心,定义了操作数据库的 sql,每个sql 是一个statement. parameterType(输入类型),输入类型包括:基本类型.pojo对象类型.hashmap. a. #{} 与 ${} #{} 是向 prepareStatement 中的预处理语句中设置参数值,表示一个占位符,相当于 ? .使用占位符 #{} 可以有效防止sql 注入,在使用时不需要关心参数值的类型,mybatis 会根据参数值的类型调用不同的statement

mybatis 详解(二)------入门实例(基于XML)

通过上一小节,mybatis 和 jdbc 的区别:http://www.cnblogs.com/ysocean/p/7271600.html,我们对 mybatis有了一个大致的了解,下面我们通过一个入门实例来对mybatis有更近一步的了解. 我们用 mybatis 来对 user 表进行增删改查操作. ps:本篇博客源代码链接:http://pan.baidu.com/s/1eSEfc8i密码:j480 1.创建MySQL数据库:mybatisDemo和表:user 这里我们就不写脚本创建

利用mybatis generator插件反向生成Dao、Mapper.xml、pojo(通过maven)

直接进入主题,由于项目选择的利用maven构建,所以选择了利用maven的生成方式.(还有一种可自行百度) 一.在pom.xml中添加插件 <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configur

Mybatis中mapper.xml中的模糊查询

Mybatis中mapper.xml中的模糊查询 <!-- 方法一: 直接使用 % 拼接字符串 注意:此处不能写成 "%#{name}%" ,#{name}就成了字符串的一部分, 会发生这样一个异常: The error occurred while setting parameters, 应该写成: "%"#{name}"%",即#{name}是一个整体,前后加上% --> <if test="name != nul

MyBatis Mapper.xml文件中 $和#的区别

MyBatis Mapper.xml文件中 $和#的区别 网上有很多,总之,简略的写一下,作为备忘.例子中假设参数名为 paramName,类型为 VARCHAR . 1.优先使用#{paramName,jdbcType=VARCHAR} 写法,除了可以防止sql注入以外,它还能在参数里含有单引号的时候自动转义, 而${paramName}由于是类似于拼接sql的写法,不具备此功能. 2.注意,使用 #{paramName,jdbcType=VARCHAR} 写法的时候,模糊查询的写法为:'%'