MyBatis一对多查询
在《MyBatis》框架中如何进行处理一对多查询操作。
例如:一个用户可以有多个订单,一个订单只属于一个用户。
在操作过程中有两种方法:级联查询和分步查询(这里用的是分步查询)
分布查询是通过两次或者多次查询出结果。
在操作过程中需要用到<resultMap>元素的子元素<association>处理一对多查询
- property:指定映射到实体类的对象属性。
- column:指定表中对应的字段(即查询返回的列名)。
- select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询
实例:
1 <association property=”user” 2 select=”com.it.mappers.UserMapper.findOrdersAndUserTwo” 3 column=”user_id”/>
示例:
下面以用户和订单为例讲解一对多关联查询(实现“根据 id 查询用户及其关联的订单信息”的功能)的处理过程。
1、创建数据库:
两张表:User(用户)、Orders(订单)
SQL语句:
CREATE TABLE `order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `number` int(25) DEFAULT NULL, `user_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `userId` (`user_id`), CONSTRAINT `order_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; insert into `order`(`id`,`ordernum`,`user_id`) values (1,1000011,1),(2,1000012,2),(3,1000011,3),(4,1000012,1); DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL,
`address` varchar(20),
PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; insert into `user`(`id`,`name`) values (1,'张三'),(2,'李四'),(3,'王五'),(4,'赵六');
2、创建持久化类
创建持久化类 User 和 Order,代码分别如下。
package com.it.pojo; import java.util.List; public class User { private Integer id; private String username; private String address; private List<Orders> ordersList; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", address='" + address + '\'' + ", ordersList=" + ordersList + '}'; } //省略getter、setter }
package com.it.pojo; public class Orders { private Integer id; private String number; private Integer user_id; @Override public String toString() { return "Orders{" + "id=" + id + ", number='" + number + '\'' + ", user_id=" + user_id + ", user=" + user + '}'; } //省略getter和setter }
分步查询
UserMapper接口代码如下:
import com.it.pojo.User; import org.apache.ibatis.annotations.Param; import java.util.List; public interface UserMapper { //一对多分布查询One List<User> findUserAndOrdersStepOne(@Param("id")Integer id); }
UserMapper.xml中相映射sql语句如下:
<!--一对多分布查询第一步--> <select id="findUserAndOrdersStepOne" resultMap="userAndOrdersResultMap"> select * from tb_user where id = #{id} </select> <resultMap id="userAndOrdersResultMap" type="User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <association property="ordersList" select="com.it.mappers.OrderMapper.findUserAndOrdersTwo" column="id"/> </resultMap>
OrdersMapper接口代码如下:
import com.it.pojo.Orders; import org.apache.ibatis.annotations.Param; import java.util.List; public interface OrderMapper { // <!--一对多分布查询第二步--> List<Orders> findUserAndOrdersTwo(@Param("uid")Integer user_id); }
UOrdersMapper.xml中相映射sql语句如下:
<!--一对多分布查询第二步--> <select id="findUserAndOrdersTwo" resultType="Orders"> select * from tb_orders where user_id = #{uid} </select>
测试代码如下:
@org.junit.Test public void test(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> list = mapper.findUserAndOrdersStepOne(1); System.out.println(list); sqlSession.close(); }
运行结果如下:
DEBUG 04-10 18:27:00,165 ==> Preparing: select * from tb_user where id = ?(BaseJdbcLogger.java :137) DEBUG 04-10 18:27:00,191 ==> Parameters: 1(Integer)(BaseJdbcLogger.java :137) DEBUG 04-10 18:27:00,208 ====> Preparing: select * from tb_orders where user_id = ?(BaseJdbcLogger.java :137) DEBUG 04-10 18:27:00,209 ====> Parameters: 1(Integer)(BaseJdbcLogger.java :137) DEBUG 04-10 18:27:00,210 <==== Total: 2(BaseJdbcLogger.java :137) DEBUG 04-10 18:27:00,212 <== Total: 1(BaseJdbcLogger.java :137) [User{id=1, username='小明', address='北京', ordersList=[Orders{id=1, number='1000011', user_id=1, user=null}, Orders{id=2, number='1000012', user_id=1, user=null}]}] Process finished with exit code 0
以下是我私下画的一个草图: