Mybatis20_mybatis的多表操作8
一、一对一查询
1、一对一查询的模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

2、订单环境代码实现
2.1 数据库数据导入
/* Navicat MySQL Data Transfer Source Server : mysql Source Server Version : 50147 Source Host : localhost:3306 Source Database : test Target Server Type : MYSQL Target Server Version : 50147 File Encoding : 65001 Date: 2019-04-20 16:37:34 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for orders -- ---------------------------- DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ordertime` varchar(255) DEFAULT NULL, `total` double DEFAULT NULL, `uid` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`), CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of orders -- ---------------------------- INSERT INTO `orders` VALUES ('1', '2018-12-12', '3000', '1'); INSERT INTO `orders` VALUES ('2', '2018-12-12', '4000', '1'); INSERT INTO `orders` VALUES ('3', '2018-12-12', '5000', '2'); -- ---------------------------- -- Table structure for sys_role -- ---------------------------- DROP TABLE IF EXISTS `sys_role`; CREATE TABLE `sys_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `roleName` varchar(255) DEFAULT NULL, `roleDesc` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_role -- ---------------------------- INSERT INTO `sys_role` VALUES ('1', 'CTO', 'CTO'); INSERT INTO `sys_role` VALUES ('2', 'COO', 'COO'); -- ---------------------------- -- Table structure for sys_user_role -- ---------------------------- DROP TABLE IF EXISTS `sys_user_role`; CREATE TABLE `sys_user_role` ( `userid` int(11) NOT NULL, `roleid` int(11) NOT NULL, PRIMARY KEY (`userid`,`roleid`), KEY `roleid` (`roleid`), CONSTRAINT `sys_user_role_ibfk_1` FOREIGN KEY (`userid`) REFERENCES `sys_role` (`id`), CONSTRAINT `sys_user_role_ibfk_2` FOREIGN KEY (`roleid`) REFERENCES `user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_user_role -- ---------------------------- INSERT INTO `sys_user_role` VALUES ('1', '1'); INSERT INTO `sys_user_role` VALUES ('2', '1'); INSERT INTO `sys_user_role` VALUES ('1', '2'); INSERT INTO `sys_user_role` VALUES ('2', '2'); -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `password` varchar(50) DEFAULT NULL, `birthday` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', 'lucy', '123', '2018-12-12'); INSERT INTO `user` VALUES ('2', 'haohao', '123', '2019-12-12');
2.2 项目搭建

Order.java:
package com.itheima.domain; import java.util.Date; public class Order { private int id; private Date ordertime; private double total; //当前订单属于哪一个用户(java中实体与实体的关系是通过实体的引用去维系的) private User user; public int getId() { return id; } public void setId(int id) { this.id = id; } public Date getOrdertime() { return ordertime; } public void setOrdertime(Date ordertime) { this.ordertime = ordertime; } public double getTotal() { return total; } public void setTotal(double total) { this.total = total; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Order{" + "id=" + id + ", ordertime=" + ordertime + ", total=" + total + ", user=" + user + '}'; } }
sqlMapConfig.xml中加载映射文件:
<?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标签加载外部properties文件-->
<properties resource="jdbc.properties"/>
<!--定义别名-->
<typeAliases>
<typeAlias type="com.itheima.domain.User" alias="user"/>
<typeAlias type="com.itheima.domain.Order" alias="order"/>
</typeAliases>
<!--数据源环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<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>
<!--加载映射文件-->
<mappers>
<mapper resource="com/itheima/mapper/UserMapper.xml"/>
<mapper resource="com/itheima/mapper/OrderMapper.xml"/>
</mappers>
</configuration>
3、一对一查询的语句
对应的sql语句:select *,o.id oid from orders o,user u where o.uid = u.id;
查询的结果如下:

4、创建OrderMapper接口
package com.itheima.mapper; import com.itheima.domain.Order; import java.util.List; public interface OrderMapper { public List<Order> findAll(); }
5、配置OrderMapper.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.itheima.mapper.OrderMapper"> <resultMap id="orderMap" type="order"> <!--手动指定字段与实体属性的映射关系 column:数据库表的字段名称 property:实体的属性名称 --> <id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> <result column="uid" property="user.id"></result> <result column="username" property="user.username"></result> <result column="password" property="user.password"></result> <result column="birthday" property="user.birthday"></result> </resultMap> <!--<select id="findAll" resultType="order">--> <select id="findAll" resultMap="orderMap"> select *,o.id oid from orders o,user u where o.uid=u.id; </select> </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.itheima.mapper.OrderMapper"> <resultMap id="orderMap" type="order"> <!--手动指定字段与实体属性的映射关系 column:数据库表的字段名称 property:实体的属性名称 --> <id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> <!-- property:当前实体order中的属性名称(private User user) javaType:当前实体order中的属性的类型(User) --> <association property="user" javaType="user"> <id column="uid" property="id"></id> <id column="username" property="username"></id> <id column="password" property="password"></id> <id column="birthday" property="birthday"></id> </association> </resultMap> <!--<select id="findAll" resultType="order">--> <select id="findAll" resultMap="orderMap"> select *,o.id oid from orders o,user u where o.uid=u.id; </select> </mapper>
6、测试类

package com.itheima.test; import com.itheima.domain.Order; import com.itheima.mapper.OrderMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { @Test public void test1() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); OrderMapper mapper = sqlSession.getMapper(OrderMapper.class); List<Order> orderList = mapper.findAll(); for (Order order : orderList) { System.out.println(order); } sqlSession.commit(); sqlSession.close(); } }
执行test1,查看控制台打印结果:

二、一对多/多对一查询
1、一对多查询的模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

2、一对多查询的语句
对应的sql语句:select *,o.id oid from user u,orders o where u.id=o.uid;
查询的结果如下:

3、修改User实体
package com.itheima.domain; import java.util.Date; import java.util.List; public class User { private int id; private String username; private String password; private Date birthday; //描述的是当前用户存在哪些订单 private List<Order> orderList; 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<Order> getOrderList() { return orderList; } public void setOrderList(List<Order> orderList) { this.orderList = orderList; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", birthday=" + birthday + ", orderList=" + orderList + '}'; } }
4、修改UserMapper接口
package com.itheima.mapper; import com.itheima.domain.User; import java.util.List; public interface UserMapper { public List<User> findAll(); }
5、配置UserMapper.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.itheima.mapper.UserMapper"> <resultMap id="userMap" type="user"> <id column="uid" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="birthday" property="birthday"></result> <!--配置集合信息 property:集合名称 ofType:当前集合中的数据类型(因为核心配置文件中对com.itheima.domain.Order起了别名order所以赋值order) --> <collection property="orderList" ofType="order"> <!--封装order的数据--> <id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> </collection> </resultMap> <select id="findAll" resultMap="userMap"> select *,o.id oid from user u,orders o where u.id=o.uid; </select> </mapper>
6、测试类MybatisTest.java:
package com.itheima.test; import com.itheima.domain.Order; import com.itheima.domain.User; import com.itheima.mapper.OrderMapper; import com.itheima.mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { @Test public void test2() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.findAll(); for (User user : userList) { System.out.println(user); } sqlSession.commit(); sqlSession.close(); } }
执行test2,查看控制台打印结果:

三、多对多查询
1、多对多查询的模型
用户表和角色表的关系为:一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色

2、多对多查询的语句:
对应的sql语句:select * from user u,sys_user_role ur,sys_role r where u.id=ur.userid and ur.roleid=r.id;
查询的结果如下:

3、 创建Role实体,修改User实体
package com.itheima.domain; public class Role { private int id; private String roleName; private String roleDesc; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getRoleName() { return roleName; } public void setRolename(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } @Override public String toString() { return "Role{" + "id=" + id + ", rolename='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; } }
package com.itheima.domain; import java.util.Date; import java.util.List; public class User { private int id; private String username; private String password; private Date birthday; //描述的是当前用户存在哪些订单 private List<Order> orderList; //描述的是当前用户具备哪些角色 private List<Role> roleList; 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<Order> getOrderList() { return orderList; } public void setOrderList(List<Order> orderList) { this.orderList = orderList; } public List<Role> getRoleList() { return roleList; } public void setRoleList(List<Role> roleList) { this.roleList = roleList; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", birthday=" + birthday + ", orderList=" + orderList + ", roleList=" + roleList + '}'; } }
4、添加UserMapper接口方法
package com.itheima.mapper; import com.itheima.domain.User; import java.util.List; public interface UserMapper { public List<User> findUserAndRoleAll(); }
5、配置UserMapper.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.itheima.mapper.UserMapper">
<resultMap id="userRoleMap" type="user">
<!--user的信息-->
<id column="userid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--user内部的roleList信息-->
<collection property="roleList" ofType="com.itheima.domain.Role">
<id column="roleid" property="id"></id>
<result column="roleName" property="roleName"></result>
<result column="roleDesc" property="roleDesc"></result>
</collection>
</resultMap>
<select id="findUserAndRoleAll" resultMap="userRoleMap">
select * from user u,sys_user_role ur,sys_role r where u.id=ur.userid and ur.roleid=r.id;
</select>
</mapper>
6、测试类MybatisTest.java
package com.itheima.test; import com.itheima.domain.Order; import com.itheima.domain.User; import com.itheima.mapper.OrderMapper; import com.itheima.mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { @Test public void test3() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userAndRoleAll = mapper.findUserAndRoleAll(); for (User user : userAndRoleAll) { System.out.println(user); } sqlSession.commit(); sqlSession.close(); } }
执行test3,查看控制台打印结果:

四、知识小结
MyBatis多表配置方式:
一对一配置:使用<resultMap>做配置
一对多配置:使用<resultMap>+<collection>做配置
多对多配置:使用<resultMap>+<collection>做配置,与一对多的区别就是多了一张中间表。
浙公网安备 33010602011771号