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

Mybatis框架(动态SQL及Mybatis缓存)

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

Mybatis框架(动态SQL及Mybatis缓存)

Mybatis
  • ORM:对象关系映射。每张表要和一个JavaBean对应

    • 关系->对象:指从表里查询数据,把结果封装成对应的JavaBean对象
    • 对象->关系:指把JavaBean里的数据,保存到表里对应的字段上
    • Hibernate是一个全ORM框架
    • Mybatis是一个半ORM框架:只实现了 关系->对象
  • 搭建Mybatis开发环境

    1. 创建项目,导入jar包,准备JavaBean

    2. 使用Mybatis实现功能

      1. 先创建dao接口(映射器Mapper):不需要实现类

      2. 再给每个接口创建一个xml文件(映射配置文件),主要配置每个方法的SQL语句:

        映射文件和映射器接口,要求:同名同位置

      3. 还需要创建一个全局配置文件:主要配置数据源、映射器

        全局配置文件名称随意,位置建议放到src下

      4. 可以再配置一个日志配置文件

    3. 功能测试

      //1. 加载全局配置文件
      InputStream is = Resources.getResourceAsStream("全局配置文件");
      //2. 得到一个SqlSession对象
      SqlSessionFactory factory = new SqlSesionFactoryBuilder().build(is);
      SqlSession session = factory.openSession();
      //3. 得到dao接口的代理对象
      UserDao userDao = session.getMapper(UserDao.class);
      
      //4. 释放资源
      session.close();
      is.close();
      
  • 代理方式的CURD功能实现

    1. 在dao接口里增加方法
    2. 在接口配置文件里配置SQL语句
    
        select语句
    
    
    	
        	select last_insert_id()
        
        insert语句
    
    
    	update语句
    
    
    	delete语句
    
    
  • 参数说明

    • 单参数

      • 如果参数是简单类型,SQL语句里取参数值:#{随便}
      • 如果参数是JavaBean,SQL语句里取参数值:#{JavaBean的属性名}
      • 如果参数是复杂JavaBean,SQL语句里取参数值:#{JavaBean属性名.属性名}
    • 多参数

      • SQL取值方案一:#{arg0}, #{arg1}, ....
      • SQL取值方案二:#{param1}, #{param2}, ...
      • 给参数命名,根据名称取参数值
      List search(@Param("username")String username, @Param("sex")String sex);
      
      
      
      
      	
          
      
      
    • 全局配置文件

      
      	
      
      
      	....
      
      
      	
      
      
    一、动态sql拼接 目标
    • 能够使用mybatis的标签实现动态SQL拼接
    分析

    ​ 我们在前边的学习过程中,使用的SQL语句都非常简单。而在实际业务开发中,我们的SQL语句通常是动态拼接而成的,比如:条件搜索功能的SQL语句。

    # 提供了一个功能:用户可以在页面上根据username、sex、address进行搜索
    # 用户输入的搜索条件:可以是一个条件,也可能是两个、三个
    
    # 只输入一个条件:姓名是"王"
    SELECT * FROM USER WHERe username LIKE '%王%'
    # 只输入一个条件:性别是“男”
    SELECt * FROM USER WHERe sex = '男'
    # 输入两个条件:姓名“王”,性别“男”
    SELECt * FROM USER WHERe username LIKE '%王%' AND sex = '男'
    # 输入三个条件:姓名“王”,性别“男”,地址“北京”
    SELECt * FROM USER WHERe username LIKE '%王%' AND sex = '男' AND address LIKE '%北京%';
    

    在Mybatis中,SQL语句是写在映射配置的XML文件中的。Mybatis提供了一些XML的标签,用来实现动态SQL的拼接。

    ​ 常用的标签有:

    • :用来进行判断,相当于Java里的if判断
    • :通常和if配合,用来代替SQL语句中的where 1=1
    • :用来遍历一个集合,把集合里的内容拼接到SQL语句中。例如拼接:in (value1, value2, ...)
    • :用于定义sql片段,达到重复使用的目的
    讲解 1. 准备Mybatis环境
    1. 创建java项目,导入jar包;准备JavaBean
    2. 创建映射器接口UserDao
    3. 创建映射配置文件UserDao.xml
    4. 创建全局配置文件SqlMapConfig.xml
    5. 创建日志配置文件log4j.properties
    2. 标签: 语法介绍
    
    	SQL语句内容, 如果判断为true,这里的SQL语句就会进行拼接
    
    
    使用示例
    • 根据用户的名称和性别搜索用户信息。把搜索条件放到User对象里,传递给SQL语句
    1. 映射器接口UserDao上加方法
    package com.is.fwis.dao;
    
    import com.is.fwis.domain.User;
    
    import java.util.List;
    
    
    public interface UserDao {
        
        List search1(User user);
    }
    
    1. 映射文件UserDao.xml里配置statement
    
    
    
    
        
        
            select * from user where 1=1
            
                and username like "%"#{username}"%"
            
            
                and sex = #{sex}
            
        
    
    
    1. 功能测试,在测试类里加测试方法
    package com.is.fwis;
    
    import com.is.fwis.dao.UserDao;
    import com.is.fwis.domain.User;
    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.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    
    public class SqlTest {
    
        private UserDao userDao;
        private SqlSession session;
        private InputStream is;
    
        
        @Test
        public void testSearch(){
            User user = new User();
            // user.setUsername("王");
            // user.setSex("男");
    
            List userList = userDao.search1(user);
            userList.forEach(System.out::println);
        }
    
    
        @Before
        public void init() throws IOException {
            //1. 读取全局配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2. 得到一个SqlSession对象
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            session = factory.openSession();
            userDao = session.getMapper(UserDao.class);
        }
    
        @After
        public void destroy() throws IOException {
            session.close();
            is.close();
        }
    }
    
    3. 标签 语法介绍

    在刚刚的练习的SQL语句中,我们写了where 1=1。如果不写的话,SQL语句会出现语法错误。Mybatis提供了一种代替where 1=1的技术:标签。

    代码示例

    ​ 把上一章节的实现代码进行优化,使用标签代替where 1=1

    1. 映射器UserDao的search1方法:已有,不用修改
    List search1(User user);
    
    1. 在映射文件UserDao.xml里修改SQL语句
    
    	select * from user
        
    
    
    	
            
            	
                	#{id}
                
            
            
                
                    and username like "%"#{username}"%"
                
                
                    and sex = #{sex}
                
            
        
    
    
    拓展:标签 语法介绍

    set标签用于代替update语句 的set关键字,实现动态拼接update语句,它可以用来动态包含需要更新的列,帮我们去掉多余的逗号。

    使用示例
    • 在映射器接口UserDao里添加方法
    void edit(User user);
    
    • 在映射文件UserDao.xml里配置SQL语句
    
    	update user
        
        	username = #{username},
            sex = #{sex},
            birthday = #{birthday},
        
        where id = #{id}
    
    
    • 功能测试
    @Test
    public void testEdit(){
        User user = new User();
        user.setId(51);
        user.setUsername("张三");
        
        userDao.edit(user);
        session.commit();
    }
    
    二、Mybatis的缓存

    缓存:高速的临时数据存储

    1. 准备环境

    略。按步骤准备好User和UserDao、UserDao.xml、SqlMapConfig.xml、log4j.properties

    2. 一级缓存 目标
    • 了解Mybatis的一级缓存
    讲解 一级缓存介绍
    • 一级缓存,是SqlSession对象提供的缓存
    • 执行一次查询之后,查询的结果(JavaBean对象)会被缓存到SqlSession中。
    • 再次查询同样的数据,Mybatis会优先从缓存中查找;如果找到了,就不再查询数据库。
    一级缓存的清除
    • 当调用了SqlSession对象的修改、添加、删除、commit()、close()、clearCache()等方法时,一级缓存会被清空。
    效果演示
    package com.is.fwis;
    
    import com.is.fwis.dao.UserDao;
    import com.is.fwis.domain.User;
    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.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    
    public class CacheTest {
    
        private UserDao userDao;
        private SqlSession session;
        private InputStream is;
        private SqlSessionFactory factory;
    
        
        @Test
        public void testLevel1Cache(){
            User user1 = userDao.findById(41);
    
            //如果在这里使用SqlSession执行了增、删、改、关闭session、提交事务、clearCache方法时,Mybatis会把缓存清除掉
            session.clearCache();
    
            User user2 = userDao.findById(41);
    
            System.out.println(user1==user2);
        }
    
        @Before
        public void init() throws IOException {
            //1. 读取全局配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2. 得到一个SqlSession对象
            factory = new SqlSessionFactoryBuilder().build(is);
            session = factory.openSession();
            userDao = session.getMapper(UserDao.class);
        }
    
        @After
        public void destroy() throws IOException {
            session.close();
            is.close();
        }
    }
    
    3. 二级缓存 目标
    • 了解Mybatis二级缓存的效果
    讲解 3.1 什么是二级缓存
    • 二级缓存是Mapper级别的缓存(映射器级别的缓存)
    • 同样的映射器Mapper共享二级缓存。UserDao
    • 注意:
      • 二级缓存,缓存的是序列化之后的数据;
      • 当从缓存里取数据时,要进行反序列化还原成JavaBean对象
      • 要求JavaBean必须实现序列化接口Serializable
      • 二级缓存需要手动开启

    3.2 开启二级缓存
    1. 修改全局配置文件,开启二级缓存
    
        
        
    
    
    1. 哪个映射器要使用二级缓存,就在哪个映射文件里开启二级缓存支持

    2. 哪个方法要使用二级缓存,就在方法的配置statement上加useCache="true"

    3.3 效果演示
        
        @Test
        public void testLevel2Cache(){
            //第一次:
            SqlSession session1 = factory.openSession();
            UserDao userDao1 = session1.getMapper(UserDao.class);
            User user1 = userDao1.findById(41);
            session1.close();
    
    
            //第二次:
            SqlSession session2 = factory.openSession();
            UserDao userDao2 = session2.getMapper(UserDao.class);
            User user2 = userDao2.findById(41);
            session2.close();
    
            System.out.println(user1==user2);
        }
    
    三、嵌套查询(级联查询)

    如果要查询一条数据,有很多关联的其它数据,该如何实现呢?可以使用Mybatis的查询嵌套方式实现需求

    如下图所示:

    • 要查询一条用户数据,封装成User
    • 但是User里还要有:
      • 当前User关联的订单列表
      • 当前User关联的帐号列表
      • 当前User关联的角色列表
      • 当前User关联的收货地址列表
      • 当前User关联的用户详情
    1. 准备开发环境
    1. 创建项目,导入jar包,创建JavaBean
    2. 创建映射器接口UserDao和AccountDao
    3. 创建映射文件UserDao.xml 和AccountDao.xml
    4. 创建Mybatis的全局配置文件。 注意,要配置好别名和映射器
    5. 准备好log4j日志配置文件
    6. 编写单元测试类备用
    2. 关联一项数据 目标
    • 查询所有帐号,及关联的用户。一个帐号Account只关联一个用户User
    分析
    1. 修改实体类Account
    2. 在映射器里加方法
    3. 在映射文件配置statement:
      • 编写SQL语句,只查询所有的帐号select * from account
    • 使用resultMap封装结果集,使用association封装关联的那个User
    实现 1. 修改实体类Account
    public class Account {
        private Integer id;
        private Integer uid;
        private Double money;
    
        private User user;
     
        //get/set...
    }
    
    2. 在AccountDao里增加方法
        
        List queryAllAccount();
    
    3. 在AccountDao.xml里配置statement
    
        select * from account
    
    
        
        
        
    
        
        
    
    
    4. 编写“查询一个用户”的方法 1. 在UserDao里增加方法
        
        User findById(Integer uid);
    
    2. 在UserDao.xml配置statement
    
        select * from user
    
    
        
        
        
        
        
    
        
        
    
    
    3. 准备根据用户id查询帐号集合的功能 3.1 在AccountDao里增加方法
        
        List findAccountsByUid(Integer uid);
    
    3.2 在AccountDao.xml里配置statement
    
        
            
            
            
            
            
    
            
                
                
                
            
        
    
    
    4) 在单元测试类中编写测试代码
        
        @Test
        public void testQueryAllUser(){
            List userList = userDao.queryAllUser();
            userList.forEach(System.out::println);
        }
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644995.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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