栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

二、MyBatis复杂映射&配置文件深入

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

二、MyBatis复杂映射&配置文件深入

一、MyBatis高级查询 1.resultMap属性

前言:在建立对象关系映射时,如果实体类中的属性名和数据库表中的字段名一致,使用resultType属性可以将查询结果自动封装到实体类中。
那如果实体类中的属性名和数据库表中的字段名不一致,就需要使用restltMap实现将查询结果手动封装到实体类中。

(1)编写UserMapper接口
package cn.xuguowen.mapper;

import cn.xuguowen.pojo.User;

import java.util.List;


public interface UserMapper {
    
    List findAll();
}
(2)编写UserMapper.xml文件



    

    
    
        
        
        
        
        
        
        
        
    

    
        select * from user
    

(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 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 * from user where id = #{id} and username = #{username}
    
③:测试
	@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 * from user where username like #{username}
    
③:测试
	 @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 users = mapper.findByUserName1("%王%");
        for (User user : users) {
            System.out.println(user);
        }
        sqlSession.close();
    }
(2)方式二:${} ①:编写UserMapper接口
	 
    List findByUserName2(String username);
②:UserMapper.xml
	
        select * from user 
        
        
            
                and id = #{id}
            
            
            
                and username = #{usernameabc}
            
        
    
③:测试
    @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 users = mapper.findByIdAndUsername(user);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }
(2)动态SQL之 set

需求:动态更行user表中的数据,如果该属性有值就更新,没有值就不处理。

①:编写UserMapper接口
	
    void updateSet(User user);
②:UserMapper.xml
	
        update user  
        
        
            
                username = #{usernameabc},
            
            
                birthday = #{birthdayabc},
            
            
                sex = #{sexabc},
            
            
                address = #{addressabc},
            
        
        where id = #{id}
    
③:测试
	
    @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遍历才能实现。

 标签用于遍历集合,它的属性:
		• collection:代表要遍历的集合
		• open:代表语句的开始部分
		• close:代表语句的结束部分
		• item:代表遍历集合的每个元素,生成的变量名
		• sperator:代表分隔符
传入的参数是集合 ①:编写UserMapper接口
	
    List findByList(List ids);
②:UserMapper.xml
        
        
        select * from user
        
            
            
                #{id} 
            
        
    
③:测试
	 
    @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 ids = new ArrayList<>();
        ids.add(1);
        ids.add(5);
        ids.add(7);

        List users = mapper.findByList(ids);
        for (User user : users) {
            System.out.println(user);
        }
    }

传入的参数是数组 ①:编写UserMapper接口
 	
    List findByArray(Integer[] ids);
②:UserMapper.xml
    

    
    

三、MyBatis核心配置文件深入 1.plugins标签

MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据。

开发步骤 ①:导入通用PageHelper依赖坐标
	
        
            com.github.pagehelper
            pagehelper
            3.7.5
        
        
            com.github.jsqlparser
            jsqlparser
            0.9.1
        
②:在mybatis核心配置文件中配置PageHelper插件
	
    
        
        
            
            
        
    
③:测试分页代码实现
	
    @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);
        // 在调用查询之前,一定要进行分页参数的设置
        // 参数一pageNum:表示当前是第几页
        // 参数二pageSize:表示每页显示的条数
        PageHelper.startPage(1, 2);

        List all = mapper.findAll();
        for (User user : all) {
            System.out.println(user);
        }

        // 获取其他的分页信息
        PageInfo pageInfo = new PageInfo<>(all);  // 泛型和传入list集合的泛型一致
        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;
-- ----------------------------
-- Records of orders
-- ----------------------------
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');
-- ----------------------------
-- 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', 'CEO', 'CEO');
-- ----------------------------

-- 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');

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;    // 关联user表

    // 因为mybatis中把多对一的关系看做是一对一的关系
    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 findAllWithUser();
}
c):OrdersMapper.xml

    
    
        
        
        
        
        
        
            
            
            
            
            
            
        
    

    
        SELECT * FROM orders o LEFT JOIN USER u ON o.uid = u.id
    

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 = 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 ordersList;
}

public class Orders {
    private Integer id;
    private String ordertime;
    private double total;   // 订单价格
    private Integer uid;    // 关联user表

    // 因为mybatis中把多对一的关系看做是一对一的关系
    private User user;      // 表示当前订单属于哪个用户
}
b):UserMapper接口
public interface UserMapper {
    
    List findAllWithOrders();
}
c):UserMapper.xml


    
        
        
        
        
        
        
        
            
            
            
            
        
    

    
        
        
        SELECt u.*,o.id oid,o.ordertime,o.total,o.uid FROM USER u LEFT JOIN
            orders o ON u.id = o.uid;
    

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 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 ordersList;

    // 表示多的关系:当前用户具备的角色列表
    private List roleList;
}
public class Role {
    private Integer id;
    private String rolename;
    private String roleDesc;
}
b):UserMapper接口
	
    List findAllWithRole();
c):UserMapper.xml
    
        
        
        
        
        
        
            
            
            
        
    
    
        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
    
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 allWithRole = mapper.findAllWithRole();
        for (User user : allWithRole) {
            System.out.println(user);
        }
        sqlSession.close();
    }

4.总结
* 多对一(一对一)配置:使用+做配置
* 一对多配置:使用+做配置
* 多对多配置:使用+做配置
* 多对多的配置跟一对多很相似,难度在于SQL语句的编写。

五、MyBatis嵌套查询 1.什么是嵌套查询

嵌套查询就是将原来多表查询中的联合查询语句拆成单个表的查询,再使mybatis的语法嵌套在一起。
例如:查询一个订单,与此同时查询出该订单所属的用户信息

2.一对一嵌套查询 ①:介绍

需求:查询一个订单,与此同时查询出该订单所属的用户信息
一对一查询语句

 -- 1.先查询订单信息
 SELECT * FROM orders;
 -- 2.再根据订单表中的uid查询用户信息
 SELECt * FROM USER WHERe id = #{uid}
②:代码实现 a):OrdersMapper接口
 	
    List findAllWithUser2();
b):OrdersMapper.xml
    
        
        
        
        
        

        
    
    
        
        select * from user where id = #{id}
    
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 allWithUser2 = mapper.findAllWithUser2();
        for (Orders orders : allWithUser2) {
            System.out.println(orders);
        }
        sqlSession.close();
    }

3.一对多嵌套查询 ①:介绍

需求:查询所有用户,与此同时查询出该用户具有的订单
一对多查询语句

-- 1.先查询出所用用户
SELECT * FROM USER;
-- 2.根据id查询出每个用户所具有的订单信息
SELECt * FROM orders WHERe uid = #{id}
②:代码实现 a):UserMapper接口
	 
    List findAllWithOrders2();
b):UserMapper.xml
    
        
        
        
        
        
        
    
    
        select * from orders where uid = #{id}
    
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 allWithOrders2 = mapper.findAllWithOrders2();

        for (User user : allWithOrders2) {
            System.out.println(user);
        }

        sqlSession.close();
    }

4.多对多嵌套查询 ①:介绍

需求:查询所有用户,同时查询出该用户的所有角色
多对多查询语句

-- 1.先查询出所用用户
SELECT * FROM USER;
-- 2.根据id查询出每个用户所具有的订单信息
SELECt * FROM orders WHERe uid = #{id}
②:代码实现 a):UserMapper接口
	
    List findAllWithRole2();
b):UserMapper.xml
	
    
        
        
        
        
        
        
    
    
        SELECT * FROM sys_role r INNER JOIN sys_user_role ur ON r.id = ur.roleid
		WHERe ur.userid = #{id}
    

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 allWithRole2 = mapper.findAllWithRole2();
        for (User user : allWithRole2) {
            System.out.println(user);
        }
        sqlSession.close();
    }
③:总结
一对一配置:使用+做配置,通过column条件,执行select查询
一对多配置:使用+做配置,通过column条件,执行select查询
多对多配置:使用+做配置,通过column条件,执行select查询
优点:简化多表查询操作
缺点:执行多次sql语句,浪费数据库性能
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/284111.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号