• Mybatis中的关联映射和查询


    一、商品订单数据模型
    1、数据表
    这里定义了四个表,分别表示用户,商品,订单,和订单详情。
    用户表user
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) NOT NULL COMMENT '用户名称',
      `birthday` date DEFAULT NULL COMMENT '生日',
      `sex` char(1) DEFAULT NULL COMMENT '性别',
      `address` varchar(256) DEFAULT NULL COMMENT '地址',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8

    表中的数据如下图:



    商品表items
    CREATE TABLE `items` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(32) NOT NULL COMMENT '商品名称',
      `price` float(10,1) NOT NULL COMMENT '商品定价',
      `detail` text COMMENT '商品描述',
      `pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
      `createtime` datetime NOT NULL COMMENT '生产日期',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
    表中的数据如下图:

    订单表orders
    CREATE TABLE `orders` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_id` int(11) NOT NULL COMMENT '下单用户id',
      `number` varchar(32) NOT NULL COMMENT '订单号',
      `createtime` datetime NOT NULL COMMENT '创建订单时间',
      `note` varchar(100) DEFAULT NULL COMMENT '备注',
      PRIMARY KEY (`id`),
      KEY `FK_orders_1` (`user_id`),
      CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
    在订单表中有一个外键user_id,和用户表user中的id相关联。
    表中的数据如下图:


    订单详情orderdetail
    CREATE TABLE `orderdetail` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `orders_id` int(11) NOT NULL COMMENT '订单id',
      `items_id` int(11) NOT NULL COMMENT '商品id',
      `items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
      PRIMARY KEY (`id`),
      KEY `FK_orderdetail_1` (`orders_id`),
      KEY `FK_orderdetail_2` (`items_id`),
      CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
      CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
    在订单详情表中有两个外键:orders_id和订单表orders中的id相关联;items_id和商品表items中的id相关联。
    表中的数据如下图:

    综合以上四张表,结合里面已有的数据,最终整合得到如下信息:
    张三有编号为1000010和1000011两个订单。其中1000010订单包含1个台式机和3个笔记本;1000011订单包含4个IPAD和3个笔记本。
    而李四有一个编号为1000012的订单,包含2个IPAD。
    信息如下图:


    2、表与表之间的关系
    先分析明确有外键关联的数据表。
    user和orders:
    user---->orders:一个用户可以创建多个订单,一对多。
    orders--->user:一个订单只能属于一个用户,一对一。

    orders和orderdetail:
    orders--->orderdetail:一个订单可以包括多个订单明细。因为一个订单可以购买多个商品,每个商品的购买信息都在orderdetail有一行记录。一对多关系。
    orderdetail--->orders:一个订单明细只能属于一个订单,一对一。

    orderdetail和items:
    orderdetail--->items:一个订单明细只对应一个商品信息,一对一。
    items---> orderdetail:一个商品可以属于多个订单明细(在不同的订单中) ,一对多。

    再分析没有明确关系的表之间是否有业务关系:
    orders和items:
    通过订单明细表orderdetail,orders和items可以建立关系。
    orders--->items一个订单可以包含多个商品,一对多。
    items--->orders一个商品可以属于多个订单,一对多。
    订单表和商品表是多对多关系。


    二、建立数据表对应的POJO类
    1、user.java
    package com.kang.pojo;
    
    
    import java.io.Serializable;
    import java.util.Date;
    import java.util.List;
    
    
    public class user implements Serializable {
    	
    	//属性名和数据库表的字段对应
    	private int id;
    	private String username;// 用户姓名
    	private String sex;// 性别
    	private Date birthday;// 生日
    	private String address;// 地址
    	
    	//用户创建的订单列表
    	private List<Orders> ordersList;
    	
    	
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getusername() {
    		return username;
    	}
    	public void setusername(String username) {
    		this.username = username;
    	}
    	public String getSex() {
    		return sex;
    	}
    	public void setSex(String sex) {
    		this.sex = sex;
    	}
    	public Date getBirthday() {
    		return birthday;
    	}
    	public void setBirthday(Date birthday) {
    		this.birthday = birthday;
    	}
    	public String getAddress() {
    		return address;
    	}
    	public void setAddress(String address) {
    		this.address = address;
    	}
    	public List<Orders> getOrdersList() {
    		return ordersList;
    	}
    	public void setOrdersList(List<Orders> ordersList) {
    		this.ordersList = ordersList;
    	}
    	@Override
    	public String toString() {
    		return "user [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
    				+ address + ", ordersList=" + ordersList + "]";
    	}
    
    
    
    
    }




    2、Items.java
    package com.kang.pojo;
    
    
    import java.util.Date;
    
    
    public class Items {
        private Integer id;
        private String name;
        private Float price;
        private String pic;
        private Date createtime;
        private String detail;
        
        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 == null ? null : name.trim();
        }
    
    
        public Float getPrice() {
            return price;
        }
    
    
        public void setPrice(Float price) {
            this.price = price;
        }
    
    
        public String getPic() {
            return pic;
        }
    
    
        public void setPic(String pic) {
            this.pic = pic == null ? null : pic.trim();
        }
    
    
        public Date getCreatetime() {
            return createtime;
        }
    
    
        public void setCreatetime(Date createtime) {
            this.createtime = createtime;
        }
    
    
        public String getDetail() {
            return detail;
        }
    
    
        public void setDetail(String detail) {
            this.detail = detail == null ? null : detail.trim();
        }
    
    
    	@Override
    	public String toString() {
    		return "Items [id=" + id + ", name=" + name + ", price=" + price
    				+ ", pic=" + pic + ", createtime=" + createtime + ", detail="
    				+ detail + "]";
    	}
        
    }




    3、Orders.java
    package com.kang.pojo;
    
    
    import java.util.Date;
    import java.util.List;
    
    
    public class Orders {
        private Integer id;
        private Integer userId;
        private String number;
        private Date createtime;
        private String note;
        //用户信息
        private user user;
        //订单明细
        private List<Orderdetail> orderdetails;
    
    
        public Integer getId() {
            return id;
        }
    
    
        public void setId(Integer id) {
            this.id = id;
        }
    
    
        public Integer getuserId() {
            return userId;
        }
    
    
        public void setuserId(Integer userId) {
            this.userId = userId;
        }
    
    
        public String getNumber() {
            return number;
        }
    
    
        public void setNumber(String number) {
            this.number = number == null ? null : number.trim();
        }
    
    
        public Date getCreatetime() {
            return createtime;
        }
    
    
        public void setCreatetime(Date createtime) {
            this.createtime = createtime;
        }
    
    
        public String getNote() {
            return note;
        }
    
    
        public void setNote(String note) {
            this.note = note == null ? null : note.trim();
        }
    
    
    	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 "Orders [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
    				+ ", note=" + note + ", user=" + user + ", orderdetails=" + orderdetails + "]";
    	}
    
    
        
    }




    4、Orderdetail.java
    package com.kang.pojo;
    
    
    public class Orderdetail {
        private Integer id;
        private Integer ordersId;
        private Integer itemsId;
        private Integer itemsNum;
        //明细对应的商品信息
        private Items items;
        
        public Integer getId() {
            return id;
        }
    
    
        public void setId(Integer id) {
            this.id = id;
        }
    
    
        public Integer getOrdersId() {
            return ordersId;
        }
    
    
        public void setOrdersId(Integer ordersId) {
            this.ordersId = ordersId;
        }
    
    
        public Integer getItemsId() {
            return itemsId;
        }
    
    
        public void setItemsId(Integer itemsId) {
            this.itemsId = itemsId;
        }
    
    
        public Integer getItemsNum() {
            return itemsNum;
        }
    
    
        public void setItemsNum(Integer itemsNum) {
            this.itemsNum = itemsNum;
        }
    
    
    	public Items getItems() {
    		return items;
    	}
    
    
    	public void setItems(Items items) {
    		this.items = items;
    	}
    
    
    	@Override
    	public String toString() {
    		return "Orderdetail [id=" + id + ", ordersId=" + ordersId
    				+ ", itemsId=" + itemsId + ", itemsNum=" + itemsNum + "]";
    	}
        
    }



    二、一对一查询
    这里对Mybatis的基础配置信息不再列出,只分析对应的映射文件的内容。
    业务需求:查询出订单信息,并且关联查询出创建订单的用户信息。
    1、构想查询的SQL语句
    查询涉及的数据表:orders和user。
    查询的结果信息:orders表的全部字段信息和user的三个信息。
    如何关联:通过外键orders.user_id = user.id。
    SQL查询语句如下:
    SELECT
    orders.*,
    user.username,
    user.sex,
    user.address
    FROM
    orders,
    user
    WHERE orders.user_id = user.id

    2、实现方案
    第一种:使用POJO扩展类来映射,从而避免使用resultMap。
    首先根据查询结果的形式定义POJO类:这个类继承自Orders类。
    package com.kang.pojo;
    //通过此类映射订单和用户查询的结果,让此类继承包括字段较多的pojo类。
    public class OrdersCustom extends Orders{
    	
    	//添加用户属性
    	/*user.username,
    	  user.sex,
    	  user.address */
    	
    	private String username;
    	private String sex;
    	private String address;
    	public String getusername() {
    		return username;
    	}
    	public void setusername(String username) {
    		this.username = username;
    	}
    	public String getSex() {
    		return sex;
    	}
    	public void setSex(String sex) {
    		this.sex = sex;
    	}
    	public String getAddress() {
    		return address;
    	}
    	public void setAddress(String address) {
    		this.address = address;
    	}
    	@Override
    	public String toString() {
    		return "OrdersCustom [username=" + username + ", sex=" + sex + ", address=" + address + "]";
    	}
    
    
    }

    然后再映射XML文件中用resultType来指定。
    <!-- 查询订单关联查询用户信息,使用 resultType -->
    	<select id="findOrdersuser" resultType="com.kang.pojo.OrdersCustom">
    		SELECT
    		orders.*,
    		user.username,
    		user.sex,
    		user.address
    		FROM
    		orders,
    		user
    		WHERE orders.user_id
    		= user.id
    	</select>

    之后在接口类中定义相关的方法
    public interface OrdersMapperCustom {
    	//查询订单关联查询用户信息
    	public List<OrdersCustom> findOrdersuser()throws Exception;
    }
    

    最后进行测试
    public class OrderTest {
    	// 会话工厂
    	private SqlSessionFactory sqlSessionFactory;
    	@Before
    	public void createSqlSessionFactory() throws IOException {
    		// 配置文件SqlMapConfig.xml在类路径下
    		String resource = "SqlMapConfig.xml";
    		// 得到配置文件流
    		InputStream inputStream = Resources.getResourceAsStream(resource);
    		// 创建会话工厂,传入mybatis的配置文件信息
    		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    
    	}
    
    
    	@Test
    	public void testFindOrdersuser() throws Exception {
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		// 创建代理对象
    		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
    		// 调用maper的方法
    		List<OrdersCustom> list = ordersMapperCustom.findOrdersuser();
    
    
    		//System.out.println(list);
    
    
    		for (OrdersCustom ordersCustom : list) {
    			System.out.println(ordersCustom);
    		}
    		sqlSession.close();
    	}
    }


    测试结果:




    第二种:不使用POJO扩展类
    我们可以在Orders类中添加一个属性user,然后把查询结果映射到Orders即可。
    //用户信息
    private user user;
    //提供get/set方法。

    在XML中使用resultMap来映射。
    首先定义一个resultMap片段,以供引用。
    <!-- type表示订单查询关联用户的resultMap 将整个查询的结果映射到com.kang.pojo.Orders中 -->
    	<resultMap type="com.kang.pojo.Orders" id="OrdersuserResultMap">
    		<!-- 配置映射的订单信息 -->
    		<!-- id:指定查询列中的唯一标识,也就是订单信息的中的唯一标识。如果有多个列组成唯一标识,配置多个id。 
                         column:数据库中订单信息表的唯一标识列,通常就是主键。 
                         property:订单信息表的唯一标识列所映射到Orders类中哪个属性。
                     -->
    		<id column="id" property="id" />
    		<result column="user_id" property="userId" />
    		<result column="number" property="number" />
    		<result column="createtime" property="createtime" />
    		<result column="note" property="note" />
    
    
    		<!-- 配置映射的关联的用户信息 -->
    		<!-- association:用于映射关联查询单个对象的信息。 
                         property:要将关联查询的用户信息映射到Orders中哪个属性。 
                     -->
    		<association property="user" javaType="com.kang.pojo.user">
    			<!-- id:关联查询用户的唯一标识。column:指定唯一标识用户信息的列,通常就是外键。 javaType:映射到user的哪个属性 -->
    			<id column="user_id" property="id" />
    			<result column="username" property="username" />
    			<result column="sex" property="sex" />
    			<result column="address" property="address" />
    
    
    		</association>
    	</resultMap>

    然后在XML映射文件中引用该resultMap。
    <!-- 查询订单关联查询用户信息,使用resultmap -->
    	<select id="findOrdersuserResultMap" resultMap="OrdersuserResultMap">
    		SELECT
    		orders.*,
    		user.username,
    		user.sex,
    		user.address
    		FROM
    		orders,
    		user
    		WHERE orders.user_id
    		= user.id
    	</select>
    在接口中添加相应的方法
    //查询订单关联查询用户使用resultMap
    	public List<Orders> findOrdersuserResultMap()throws Exception;
    


    在测试类中添加测试方法:
           
     @Test
    	public void testFindOrdersuserResultMap() throws Exception {
    
    
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		// 创建代理对象
    		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
    
    
    		// 调用maper的方法
    		List<Orders> list = ordersMapperCustom.findOrdersuserResultMap();
    
    
    		//System.out.println(list);
                    for (Orders orders : list) {
    			System.out.println(orders);
    		}
    
    
    		sqlSession.close();
    	}

    测试结果:


    详细结果:
    DEBUG [main] - <==      Total: 3
    Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=null]
    Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=null]
    Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=User [id=2, username=李四, sex=1, birthday=null, address=北京市, ordersList=null], orderdetails=null]
    DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

    3、resultType和resultMap实现一对一查询的比较
    resultType:使用resultType实现较为简单,如果pojo类中没有包括查询出来的列名,需要在其中增加列名对应的属性,即可完成映射。
    resultMap:需要单独定义resultMap,实现较为麻烦。如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。
    如果没有查询结果的特殊要求建议使用resultType。resultMap可以实现延迟加载,resultType无法实现延迟加载。


    三、实现一对多查询
    业务需求:查询出所有的订单并关联查询出订单的用户和其中的订单明细。
    1、构想查询的SQL语句
    查询涉及的数据表:orders,user和orderdetail。
    查询的结果信息:orders表的全部字段信息+user的三个信息+订单明细的四个信息。
    如何关联:通过外键orders.user_id = user.id关联用户查询;通过外键orders.id=orderdetail.orders_id关联查询订单明细。
    SQL查询语句如下:
    SELECT
    orders.*,
    user.username,
    user.sex,
    user.address,
    orderdetail.id orderdetail_id,
    orderdetail.items_id,
    orderdetail.items_num,
    orderdetail.orders_id
    FROM
    orders,
    user,
    orderdetail
    WHERE orders.user_id = user.id AND orders.id=orderdetail.orders_id

    2、实现方案
    使用resultMap来实现一对多关联。
    首先需要在Orders的类中添加一个属性,来表示订单明细表。
    //订单明细
    private List<Orderdetail> orderdetails;
    //提供get/set方法。

    然后在XML中使用resultMap来映射,这里采用了继承。
    <!-- 订单关联用户和订单明细的resultMap。使用extends继承,不用在中配置订单信息和用户信息的映射 -->
    	<resultMap type="com.kang.pojo.Orders" id="OrdersAndOrderDetailResultMap"
    		extends="OrdersuserResultMap">
    		<!-- 订单信息继承而来 -->
    		<!-- 用户信息继承而来 -->
    		<!-- 使用extends继承,不用配置订单信息和用户信息的映射 -->
    		<!-- 订单明细信息:一个订单关联查询出了多条明细,要使用collection进行一对多映射。
                         collection:对关联查询到多条记录映射到集合对象中。 
    		     property:将关联查询到多条记录映射到com.kang.pojo.Orders哪个属性 。
                         ofType:指定映射到list集合属性中pojo的类型。 
                     -->
    		<collection property="orderdetails" ofType="com.kang.pojo.Orderdetail">
    			<!-- id:订单明细唯一标识,一般就是主键,注意这里使用了别名,结合SQL语句一看便知。
                                 property:要将订单明细的唯一标识映射到com.kang.pojo.Orderdetail的哪个属性 -->
    			<id column="orderdetail_id" property="id" />
    			<result column="items_id" property="itemsId" />
    			<result column="items_num" property="itemsNum" />
    			<result column="orders_id" property="ordersId" />
    		</collection>
    	</resultMap>

    然后在XML映射文件中引用该resultMap。
    <!-- 查询订单关联查询用户及订单明细,使用resultmap -->
    	<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
    		SELECT
    		orders.*,
    		user.username,
    		user.sex,
    		user.address,
    		orderdetail.id orderdetail_id,
    		orderdetail.items_id,
    		orderdetail.items_num,
    		orderdetail.orders_id
    		FROM
    		orders,
    		user,
    		orderdetail
    		WHERE orders.user_id = user.id AND orders.id=orderdetail.orders_id
    	</select>
    在接口中添加相应的方法
    //查询订单(关联用户)及订单明细
    	public List<Orders>  findOrdersAndOrderDetailResultMap()throws Exception;

    在测试类中添加测试方法:
            @Test
    	public void testFindOrdersAndOrderDetailResultMap() throws Exception {
    
    
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		// 创建代理对象
    		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
    
    
    		// 调用maper的方法
    		List<Orders> list = ordersMapperCustom.findOrdersAndOrderDetailResultMap();
                    for (Orders orders : list) {
    			System.out.println(orders);
    		}
    		sqlSession.close();
    	}

    测试结果:


    详细结果:
    DEBUG [main] - <==      Total: 5
    Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=[Orderdetail [id=1, ordersId=3, itemsId=1, itemsNum=1], Orderdetail [id=2, ordersId=3, itemsId=2, itemsNum=3]]]
    Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=[Orderdetail [id=3, ordersId=4, itemsId=3, itemsNum=4], Orderdetail [id=4, ordersId=4, itemsId=2, itemsNum=3]]]
    Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=User [id=2, username=李四, sex=1, birthday=null, address=北京市, ordersList=null], orderdetails=[Orderdetail [id=5, ordersId=5, itemsId=3, itemsNum=2]]]
    DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

    3、总结
    mybatis使用resultMap中collection实现一对查询,它可以把关联查询的多条记录映射到一个list集合属性中。
    一对多查询也可以使用resultType实现:
    我们将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。


    四、实现多对多查询
    业务需求:查询出所有订单,并关联查询出订单的用户,订单的明细以及订单中的商品信息。而订单和商品信息之间就是多对多关系。
    1、构想查询的SQL语句
    查询涉及的数据表:orders,user,orderdetail和items。
    查询的结果信息:orders表的全部字段信息+user的四个信息+orderdetail的四个信息+items的三个信息。
    如何关联:通过外键orders.user_id = user.id关联用户查询;通过外键orders.id=orderdetail.orders_id关联查询订单明细;通过外键orderdetail.items_id = items.id关联查询商品信息;
    SQL查询语句如下:
    SELECT
    orders.*,
    user.username,
    user.sex,
    user.birthday,
    user.address,
    orderdetail.id orderdetail_id,
    orderdetail.items_id,
    orderdetail.items_num,
    orderdetail.orders_id,
    items.name items_name,
    items.detail items_detail,
    items.price items_price
    FROM
    orders,
    user,
    orderdetail,
    items
    WHERE orders.user_id = user.id 
    AND orderdetail.orders_id=orders.id 
    AND orderdetail.items_id = items.id

    2、实现方案
    使用resultMap来实现多对多关联。
    我们可以将查询结果映射到user中。
    首先在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist。
    然后在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials。
    最后在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items。
    这样我们通过user类就可得到所有我们查询到的信息。
    这里不去展示具体过程,可参考上面提供的POJO类即可。
    定义好POJO了类后,我们在XML中使用resultMap来映射,这里进行了collection的嵌套。
    <!-- 查询用户及购买的商品 -->
    	<resultMap type="com.kang.pojo.user" id="userAndItemsResultMap">
    		<!-- 用户信息 -->
    		<id column="user_id" property="id" />
    		<result column="username" property="username" />
    		<result column="sex" property="sex" />
    		<result column="address" property="address" />
    		<result column="birthday" property="birthday" />
    
    
    		<!-- 订单信息 一个用户对应多个订单,使用collection映射 -->
    		<collection property="ordersList" ofType="com.kang.pojo.Orders">
    			<id column="id" property="id" />
    			<result column="user_id" property="userId" />
    			<result column="number" property="number" />
    			<result column="createtime" property="createtime" />
    			<result column="note" property="note" />
    
    
    			<!-- 订单明细,一个订单包括多个明细 -->
    			<collection property="orderdetails" ofType="com.kang.pojo.Orderdetail">
    				<id column="orderdetail_id" property="id" />
    				<result column="items_id" property="itemsId" />
    				<result column="items_num" property="itemsNum" />
    				<result column="orders_id" property="ordersId" />
    
    
    				<!-- 商品信息 一个订单明细对应一个商品 -->
    				<association property="items" javaType="com.kang.pojo.Items">
    					<id column="items_id" property="id" />
    					<result column="items_name" property="name" />
    					<result column="items_detail" property="detail" />
    					<result column="items_price" property="price" />
    				</association>
    			</collection>
    		</collection>
    	</resultMap>

    然后在XML映射文件中引用该resultMap。
    <!-- 查询用户及购买的商品信息,使用resultmap -->
    	<select id="finduserAndItemsResultMap" resultMap="userAndItemsResultMap">
    		SELECT
    		orders.*,
    		user.username,
    		user.sex,
    		user.birthday,
    		user.address,
    		orderdetail.id orderdetail_id,
    		orderdetail.items_id,
    		orderdetail.items_num,
    		orderdetail.orders_id,
    		items.name items_name,
    		items.detail items_detail,
    		items.price items_price
    		FROM
    		orders,
    		user,
    		orderdetail,
    		items
    		WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND
    		orderdetail.items_id = items.id
    	</select>

    在接口中添加相应的方法
    //查询用户购买商品信息
    	public List<User>  findUserAndItemsResultMap()throws Exception;
    在测试类中添加测试方法:
            @Test
    	public void testFindUserAndItemsResultMap() throws Exception {
    
    
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		// 创建代理对象
    		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
    
    
    		// 调用maper的方法
    		List<User> list = ordersMapperCustom.findUserAndItemsResultMap();
    
    
    		//System.out.println(list);
    		for (User user : list) {
    			System.out.println(user);
    		}
    		sqlSession.close();
    	}


    测试结果:




    详细结果:
    DEBUG [main] - <==      Total: 5
    User [id=1, username=张三, sex=2, birthday=Tue Oct 27 00:00:00 CST 1998, address=成都市, ordersList=[Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=null, orderdetails=[Orderdetail [id=1, ordersId=3, itemsId=1, itemsNum=1], Orderdetail [id=2, ordersId=3, itemsId=2, itemsNum=3]]], Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=null, orderdetails=[Orderdetail [id=3, ordersId=4, itemsId=3, itemsNum=4], Orderdetail [id=4, ordersId=4, itemsId=2, itemsNum=3]]]]]
    User [id=2, username=李四, sex=1, birthday=Fri Oct 01 00:00:00 CST 1993, address=北京市, ordersList=[Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=null, orderdetails=[Orderdetail [id=5, ordersId=5, itemsId=3, itemsNum=2]]]]]
    DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]
    DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

    3、总结
    一对多是多对多的特例,查询用户购买的商品信息,用户和商品的关系是多对多关系。
    需求1:
    查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)。
    企业开发中常见明细列表,用户购买商品明细列表,使用resultType将上边查询列映射到pojo输出。
    需求2:
    查询字段:用户账号、用户名称、购买商品数量、商品明细。
    使用resultMap将用户购买的商品明细列表映射到user对象中。

    五、总结

    1、resultType
    作用:
    将查询结果按照sql列名pojo属性名一致性映射到pojo中。
    使用场合:
    常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。


    2、resultMap
    使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
    association:
    作用:
    将关联查询信息映射到一个pojo对象中。
    使用场合:
    为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
    使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
    collection:
    作用:
    将关联查询信息映射到一个list集合中。
    使用场合:
    为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
    如果使用resultType无法将查询结果映射到list集合中。



  • 相关阅读:
    struts2简介
    HDU 2842 Chinese Rings(矩阵高速功率+递归)
    Cocos2d-X中国象棋的发展《五岁以下儿童》摆棋
    【Python注意事项】如何理解python中间generator functions和yield表情
    [CSS] Design for Mobile First with Tachyons
    [Angular] Configurable NgModules
    [Angular] Using useExisting provider
    [Angular] Providers and useFactory
    [Angular] Using InjectionToken
    [Angular] Test Directive
  • 原文地址:https://www.cnblogs.com/kangsir/p/6653214.html
Copyright © 2020-2023  润新知