一、MyBatis高级查询
1.resultMap属性
前言:在建立对象关系映射时,如果实体类中的属性名和数据库表中的字段名一致,使用resultType属性可以将查询结果自动封装到实体类中。 那如果实体类中的属性名和数据库表中的字段名不一致,就需要使用restltMap实现将查询结果手动封装到实体类中。
(1)编写UserMapper接口
package cn.xuguowen.mapper;
import cn.xuguowen.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> findAll();
}
(2)编写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="cn.xuguowen.mapper.UserMapper">
<resultMap id="userResultMap" type="user">
<id property="id" column="id"></id>
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<select id="findAll" resultMap="userResultMap">
select * from user
</select>
</mapper>
(3)测试
@Test
public void testFindAll() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
sqlSession.close();
}
2.多条件查询(三种)
需求:根据id和username查询user表
(1)方式一:使用 #{arg0}-#{argn} 或者 #{param1}-#{paramn} 获取参数
①:编写UserMapper接口
User findByIdAndUserName1(int id, String username);
②:UserMapper.xml
<select id="findByIdAndUserName1" resultMap="userResultMap">
select * from user where id = #{param1} and username = #{param2}
</select>
③:测试
@Test
public void testFindByIdAndUserName1() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findByIdAndUserName1(1, "王莹");
System.out.println(user);
sqlSession.close();
}
(2)方式二:使用注解,引入 @Param() 注解获取参数
①:编写UserMapper接口
User findByIdAndUserName2(@Param("id") int id, @Param("username") String username)
②:UserMapper.xml
<select id="findByIdAndUserName2" resultMap="userResultMap">
select * from user where id = #{id} and username = #{username}
</select>
③:测试
@Test
public void testFindByIdAndUserName2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findByIdAndUserName1(1, "王莹");
System.out.println(user);
sqlSession.close();
}
(3)方式三:使用pojo对象传递参数
①:编写UserMapper接口
User findByIdAndUserName3(User user);
②:UserMapper.xml
<select id="findByIdAndUserName3" resultMap="userResultMap" parameterType="user">
select * from user where id = #{id} and username = #{usernameabc}
</select>
③:测试
@Test
public void testFindByIdAndUserName3() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = new User();
user1.setId(1);
user1.setUsernameabc("王莹");
User user = mapper.findByIdAndUserName3(user1);
System.out.println(user);
sqlSession.close();
}
3.模糊查询(两种)
需求:根据username模糊查询user表
(1)方式一:#{}
①:编写UserMapper接口
List<User> findByUserName1(String username);
②:UserMapper.xml
<select id="findByUserName1" resultMap="userResultMap" parameterType="string">
select * from user where username like #{username}
</select>
③:测试
@Test
public void testFindByUserName1() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUserName1("%王%");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
(2)方式二:${}
①:编写UserMapper接口
List<User> findByUserName2(String username);
②:UserMapper.xml
<select id="findByUserName2" resultMap="userResultMap" parameterType="string">
select * from user where username like '${value}'
</select>
③:测试
@Test
public void testFindByUserName2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUserName2("%王%");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
#{}和${}区别
-
#{}:表示一个占位符
- 通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换(实体类中属性的类型和表中字段类型的转换),还可以有效防止sql注入问题。
- #{}可以接收简单数据类型的值和pojo属性值
- 如果parameterType是基本数据类型或者String类型的,并且只有一个参数时,#{}括号中的名称随便写
-
${}:表示拼接sql串
- 通过${}可以将parameterType传入的内容拼接在sql语句上,不进行jdbc类型转换,会出现sql注入问题。
- ${}可以接收简单数据类型的值和pojo属性值
- 如果parameterType中的值是基本数据类型或者是String类型的,并且只有一个参数时,${}括号里面只能是value
二、MyBatis映射文件深入
1.返回主键
应用场景:我们很多时候有这种需求,向数据库插入一条记录后,希望能立即拿到这条记录在数据库中的主键值。
(1)方式一:useGeneratedKeys属性
①:编写UserMapper接口
void saveUser1(User user);
②:UserMapper.xml
<insert id="saveUser1" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into user (username,birthday,sex,address)
values (#{usernameabc},#{birthdayabc},#{sexabc},#{addressabc})
</insert>
③:测试
@Test
public void testSaveUser1() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsernameabc("尼古拉斯·赵四");
user.setBirthdayabc(new Date());
user.setSexabc("男");
user.setAddressabc("象牙山庄");
System.out.println(user);
mapper.saveUser1(user);
System.out.println(user);
sqlSession.commit();
sqlSession.close();
注意 只适用于主键自增的数据库,mysql和sqlserver支持,oracle不行。
(2)方式二:selectKey标签
①:编写UserMapper接口
void saveUser2(User user);
②:UserMapper.xml
<insert id="saveUser2" parameterType="user">
<selectKey order="AFTER" keyColumn="id" keyProperty="id" resultType="int">
select last_insert_ID()
</selectKey>
insert into user (username,birthday,sex,address)
values (#{usernameabc},#{birthdayabc},#{sexabc},#{addressabc})
</insert>
③:测试
@Test
public void testSaveUser2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsernameabc("詹姆斯·马双");
user.setBirthdayabc(new Date());
user.setSexabc("男");
user.setAddressabc("向阳山庄");
System.out.println(user);
mapper.saveUser2(user);
System.out.println(user);
sqlSession.commit();
sqlSession.close();
}
2.动态SQL
应用场景:当我们要根据不同的条件,来执行不同的sql语句的时候,需要用到动态sql。
(1)动态SQL之 if
需求:根据id和username查询,但是不确定两个都有值
①:编写UserMapper接口
List<User> findByIdAndUsername(User user);
②:UserMapper.xml
<select id="findByIdAndUsername" parameterType="user" resultMap="userResultMap">
select * from user
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="usernameabc != null">
and username = #{usernameabc}
</if>
</where>
</select>
③:测试
@Test
public void testFindByIdUsername1() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsernameabc("王莹");
List<User> users = mapper.findByIdAndUsername(user);
for (User user1 : users) {
System.out.println(user1);
}
}
(2)动态SQL之 set
需求:动态更行user表中的数据,如果该属性有值就更新,没有值就不处理。
①:编写UserMapper接口
void updateSet(User user);
②:UserMapper.xml
<update id="updateSet" parameterType="user">
update user
<set>
<if test="usernameabc != null">
username = #{usernameabc},
</if>
<if test="birthdayabc != null">
birthday = #{birthdayabc},
</if>
<if test="sexabc != null">
sex = #{sexabc},
</if>
<if test="addressabc != null">
address = #{addressabc},
</if>
</set>
where id = #{id}
</update>
③:测试
@Test
public void testUpdateSet() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(5);
user.setUsernameabc("刘诗诗");
user.setSexabc("女");
mapper.updateSet(user);
sqlSession.commit();
sqlSession.close();
}
(3)动态SQL之 foreach
foreach主要是用来做数据的循环遍历 例如:select * from user where id in (1,2,3)这样的sql语句中,传入的参数部分必须依靠foreach遍历才能实现。
<foreach>标签用于遍历集合,它的属性:
? collection:代表要遍历的集合
? open:代表语句的开始部分
? close:代表语句的结束部分
? item:代表遍历集合的每个元素,生成的变量名
? sperator:代表分隔符
传入的参数是集合
①:编写UserMapper接口
List<User> findByList(List<Integer> ids);
②:UserMapper.xml
<select id="findByList" parameterType="list" resultMap="userResultMap">
select * from user
<where>
<foreach collection="list" open="id in (" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
③:测试
@Test
public void testFindByList() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(5);
ids.add(7);
List<User> users = mapper.findByList(ids);
for (User user : users) {
System.out.println(user);
}
}
传入的参数是数组
①:编写UserMapper接口
List<User> findByArray(Integer[] ids);
②:UserMapper.xml
<select id="findByArray" parameterType="int" resultMap="userResultMap">
select * from user
<where>
<foreach collection="array" open="id in(" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
③:测试
@Test
public void testFindByArray() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Integer[] ids = new Integer[]{1,2,5};
List<User> users = mapper.findByArray(ids);
for (User user : users) {
System.out.println(user);
}
}
3.SQL片段
应用场景:在映射文件中,可以将重复的sql语句提取出来,使用时使用include标签引用即可,最终达到sql重用的目得。
<sql id="selectUser">
select * from user
</sql>
<select id="findByList" parameterType="list" resultMap="userResultMap">
<include refid="selectUser"></include>
<where>
<foreach collection="list" open="id in (" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
<select id="findByArray" parameterType="int" resultMap="userResultMap">
<include refid="selectUser"></include>
<where>
<foreach collection="array" open="id in(" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
三、MyBatis核心配置文件深入
1.plugins标签
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据。
开发步骤
①:导入通用PageHelper依赖坐标
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
②:在mybatis核心配置文件中配置PageHelper插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
③:测试分页代码实现
@Test
public void testFindAllPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(1, 2);
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
PageInfo<User> pageInfo = new PageInfo<>(all);
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("每页显示的长度:" + pageInfo.getPageSize());
System.out.println("是否是第一页:" + pageInfo.isIsFirstPage());
System.out.println("是否是最后一页:" + pageInfo.isIsLastPage());
}
四、MyBatis多表查询
1.数据库表关系介绍
关系型数据库表关系分为
- 一对一 人和身份证号就是一对一
- 一对多 用户和订单就是一对多(一个用户可以下多个订单),订单和用户就是多对一(多个订单属于同一个用户)
- 多对多 学生和课程就是多对多
- 特例:从数据层面看,一个订单只从属于一个用户,所以MyBatis将多对一看成了一对一
案例环境准备:
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;
INSERT INTO `orders` VALUES ('1', '2020-12-12', '3000', '1');
INSERT INTO `orders` VALUES ('2', '2020-12-12', '4000', '1');
INSERT INTO `orders` VALUES ('3', '2020-12-12', '5000', '2');
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;
INSERT INTO `sys_role` VALUES ('1', 'CTO', 'CTO');
INSERT INTO `sys_role` VALUES ('2', 'CEO', 'CEO');
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;
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');
2.一对一(多对一)
①:介绍
一对一查询模型 用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户 一对一查询的需求 查询所有订单,与此同时查询出每个订单所属的用户 一对一查询语句
SELECT * FROM orders o LEFT JOIN USER u ON o.uid = u.id
②:代码实现
a):Orders实体和User实体
public class Orders {
private Integer id;
private String ordertime;
private double total;
private Integer uid;
private User user;
}
public class User {
private Integer id;
private String username;
private Date birthday;
private Character sex;
private String address;
}
b):OrdersMapper接口
public interface OrdersMapper {
List<Orders> findAllWithUser();
}
c):OrdersMapper.xml
<mapper namespace="cn.xuguowen.mapper.OrdersMapper">
<resultMap id="ordersMap" type="orders">
<id property="id" column="id"/>
<result property="ordertime" column="ordertime"/>
<result property="total" column="total"/>
<result property="uid" column="uid"/>
<association property="user" javaType="user">
<id property="id" column="uid"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</association>
</resultMap>
<select id="findAllWithUser" resultMap="ordersMap">
SELECT * FROM orders o LEFT JOIN USER u ON o.uid = u.id
</select>
</mapper>
d):测试
@Test
public void testFindAllWithUser() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> orders = mapper.findAllWithUser();
for (Orders order : orders) {
System.out.println(order);
}
sqlSession.close();
}
2.一对多
①:介绍
一对多查询模型 用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户 一对多查询的需求 查询所有用户,与此同时查询出每个用户具有的订单 一对一查询语句
SELECT u.*,o.id oid,o.ordertime,o.total,o.uid FROM USER u LEFT JOIN orders o ON u.id = o.uid;
②:代码实现
a):Orders实体和User实体
public class User {
private Integer id;
private String username;
private Date birthday;
private Character sex;
private String address;
private List<Orders> ordersList;
}
public class Orders {
private Integer id;
private String ordertime;
private double total;
private Integer uid;
private User user;
}
b):UserMapper接口
public interface UserMapper {
List<User> findAllWithOrders();
}
c):UserMapper.xml
<mapper namespace="cn.xuguowen.mapper.UserMapper">
<resultMap id="userMap" type="cn.xuguowen.pojo.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="ordersList" ofType="cn.xuguowen.pojo.Orders">
<id property="id" column="oid"/>
<result property="ordertime" column="ordertime"/>
<result property="total" column="total"/>
<result property="uid" column="uid"/>
</collection>
</resultMap>
<select id="findAllWithOrders" resultMap="userMap">
SELECT u.*,o.id oid,o.ordertime,o.total,o.uid FROM USER u LEFT JOIN
orders o ON u.id = o.uid;
</select>
</mapper>
d):测试
@Test
public void testFindAllWithOrders() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithOrders = mapper.findAllWithOrders();
for (User users : allWithOrders) {
System.out.println(users);
}
sqlSession.close();
}
3.多对多
①:介绍
多对多查询模型 用户表和订单表的关系为:一个用户有多个角色,一个角色被多个用户使用 多对多查询的需求 查询所有用户,与此同时查询出每个用户的所有角色 多对一查询语句
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROM USER u LEFT JOIN sys_user_role ur ON u.id = ur.userid
LEFT JOIN sys_role r ON ur.roleid = r.id
②:代码实现
a):User实体和Role实体
public class User {
private Integer id;
private String username;
private Date birthday;
private Character sex;
private String address;
private List<Orders> ordersList;
private List<Role> roleList;
}
public class Role {
private Integer id;
private String rolename;
private String roleDesc;
}
b):UserMapper接口
List<User> findAllWithRole();
c):UserMapper.xml
<resultMap id="userRoleMap" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="roleList" ofType="role">
<id property="id" column="rid"/>
<result property="rolename" column="rolename"/>
<result property="roleDesc" column="roleDesc"/>
</collection>
</resultMap>
<select id="findAllWithRole" resultMap="userRoleMap">
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROM USER u
LEFT JOIN sys_user_role ur ON u.id = ur.userid
LEFT JOIN sys_role r ON ur.roleid = r.id
</select>
d):测试
@Test
public void testFindAllWithRole() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithRole = mapper.findAllWithRole();
for (User user : allWithRole) {
System.out.println(user);
}
sqlSession.close();
}
4.总结
* 多对一(一对一)配置:使用<resultMap>+<association>做配置
* 一对多配置:使用<resultMap>+<collection>做配置
* 多对多配置:使用<resultMap>+<collection>做配置
* 多对多的配置跟一对多很相似,难度在于SQL语句的编写。
五、MyBatis嵌套查询
1.什么是嵌套查询
嵌套查询就是将原来多表查询中的联合查询语句拆成单个表的查询,再使mybatis的语法嵌套在一起。 例如:查询一个订单,与此同时查询出该订单所属的用户信息
2.一对一嵌套查询
①:介绍
需求:查询一个订单,与此同时查询出该订单所属的用户信息 一对一查询语句
SELECT * FROM orders;
SELECT * FROM USER WHERE id =
②:代码实现
a):OrdersMapper接口
List<Orders> findAllWithUser2();
b):OrdersMapper.xml
<resultMap id="ordersMap2" type="orders">
<id property="id" column="id"/>
<result property="ordertime" column="ordertime"/>
<result property="total" column="total"/>
<result property="uid" column="uid"/>
<association property="user" javaType="user"
select="cn.xuguowen.mapper.UserMapper.findById" column="uid"/>
</resultMap>
<select id="findAllWithUser2" resultMap="ordersMap2">
select * from orders
</select>
c):在编写OrdersMapper.xml时需要依赖UserMapper接口和UserMapper.xml文件,因为第二条sql语句单独操作user表
UserMapper接口
User findById(Integer id);
UserMapper.xml
<select id="findById" resultType="user" parameterType="int">
select * from user where id = #{id}
</select>
d):测试
@Test
public void testFindAllWithUser2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> allWithUser2 = mapper.findAllWithUser2();
for (Orders orders : allWithUser2) {
System.out.println(orders);
}
sqlSession.close();
}
3.一对多嵌套查询
①:介绍
需求:查询所有用户,与此同时查询出该用户具有的订单 一对多查询语句
SELECT * FROM USER;
SELECT * FROM orders WHERE uid =
②:代码实现
a):UserMapper接口
List<User> findAllWithOrders2();
b):UserMapper.xml
<resultMap id="userMap2" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="ordersList" ofType="orders"
select="cn.xuguowen.mapper.OrdersMapper.findById" column="id"/>
</resultMap>
<select id="findAllWithOrders2" resultMap="userMap2">
select * from user
</select>
c):在编写UserMapper.xml时需要依赖OrdersMapper接口和OrdersMapper.xml文件,因为第二条sql语句单独操作orders表
OrdersMapper接口
List<Orders> findById(Integer id);
OrdersMapper.xml
<select id="findById" resultType="orders" parameterType="int">
select * from orders where uid = #{id}
</select>
d):测试
@Test
public void testFindAllWithOrders2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithOrders2 = mapper.findAllWithOrders2();
for (User user : allWithOrders2) {
System.out.println(user);
}
sqlSession.close();
}
4.多对多嵌套查询
①:介绍
需求:查询所有用户,同时查询出该用户的所有角色 多对多查询语句
SELECT * FROM USER;
SELECT * FROM orders WHERE uid =
②:代码实现
a):UserMapper接口
List<User> findAllWithRole2();
b):UserMapper.xml
<resultMap id="userRoleMap2" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="roleList" ofType="role"
select="cn.xuguowen.mapper.RoleMapper.findByUid" column="id" />
</resultMap>
<select id="findAllWithRole2" resultMap="userRoleMap2">
select * from user
</select>
c):在编写UserMapper.xml时需要依赖RoleMapper接口和RoleMapper.xml文件
List<Role> findByUid(Integer uid);
<mapper namespace="cn.xuguowen.mapper.RoleMapper">
<select id="findByUid" parameterType="int" resultType="role">
SELECT * FROM sys_role r INNER JOIN sys_user_role ur ON r.id = ur.roleid
WHERE ur.userid = #{id}
</select>
</mapper>
d):测试
@Test
public void testFindAllWithRole2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithRole2 = mapper.findAllWithRole2();
for (User user : allWithRole2) {
System.out.println(user);
}
sqlSession.close();
}
③:总结
一对一配置:使用<resultMap>+<association>做配置,通过column条件,执行select查询
一对多配置:使用<resultMap>+<collection>做配置,通过column条件,执行select查询
多对多配置:使用<resultMap>+<collection>做配置,通过column条件,执行select查询
优点:简化多表查询操作
缺点:执行多次sql语句,浪费数据库性能
|