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

mybatis

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

mybatis

目录
  • 框架
  • mybatis概述
            • MVC
            • ORM
          • mybatis架构
  • mybatis搭建使用
      • 参数传递
            • @Param('acc')传参
            • Map键/值串传参
      • 结果返回
            • 简单类型输出映射
            • POJO对象输出映射
            • 关联查询resultMap
      • 主键返回
      • 注解方式
      • 添加log4j日志组件
      • 单元测试
  • 懒加载
  • 动态sql
      • where
      • trim
      • choose
      • set
      • foreach
      • 特殊符号
  • 缓存
      • 一级缓存
      • 二级缓存

框架

​ 框架会将很多基本功能进行封装,程序员在框架基础上再进行业务开发

作用:简洁代码,高效开发

mybatis概述

​ 原apache的一个开源项目,2010迁移到谷歌,更名为mybatis

特点

​ 它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低

MVC

数据持久层(数据访问层 / M层):DAO,model

数据控制层(C层 control):servlet

前端(View)

ORM

Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型

​ 对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,类中的属性和表中的列一一对应。

半自动ORM框架优点

​ 用mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。用hibernate开发,只需要定义好ORM映射关系,就可以直接进行CRUD操作了。由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。虽然mybatis需要手写SQL,但相比JDBC,它提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发的效率。并且它的学习成本也比hibernate低很多

mybatis架构

mybatis搭建使用

导入MyBatis使用的jar包

        
        
            org.mybatis
            mybatis
            3.4.2
        

        
        
            mysql
            mysql-connector-java
            8.0.16
        

创建 MyBatis 全局配置文件

​ 在resources目录下创建mybatis-config.xml





    
    

    
        
        
        
        
        
        
    

    
    
        
        
        
    

    
    
        
        
            
            
            
            
                
                
                
                
                
                
            
        
    

    
    
        
        
        
    

在mapper目录下创建对应的mapper接口并定义方法

package com.ff.mybatisPro.mapper;

import com.ff.mybatisPro.model.AdminUser;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;


public interface AdminMapper {

    

    void saveAdmin(AdminUser adminUser);

    void updateAdmin(AdminUser adminUser);

    void deleteAdmin(int id);

    AdminUser selectAdminById(int id);

}

在resources.mapper目录下创建对应的mapper.xml文件

​ 基本的增删改查







    

    
    
        insert into admin(account, password, sex)
        values (#{account}, #{password}, #{sex})
    

    
        update admin
        set account=#{account},
            password=#{password},
            sex=#{sex}
        where id = #{id}
    

    
        delete
        from admin
        where id = #{id}
    
    
	
    
        select *
        from admin
        where account = #{acc}
          and password = #{pwd}
    
    
    @Test
    public void selectAdminByAccount(){
        SqlSession sqlSession = MybatisUtil.openSession();
        AdminMapper mapper = sqlSession.getMapper(AdminMapper.class);
        AdminUser adminUser = mapper.selectAdminByAccount("admin","000");
        System.out.println(adminUser);
        sqlSession.commit();
        sqlSession.close();
    }
Map键/值串传参
    
    AdminUser getAdmin(Map map);
    
    
        select count(*)
        from admin
    
POJO对象输出映射

​ resultType=“AdminUser”:返回值的类型 根据返回值的类型,创建一个对象或List 将数据库数据自动映射到java对象中,表中的类名与类中的属性名相同

List adminList();
    
        SELECT d.id,d.name dname,emp.name ename,a.account
        FROM dept d LEFT JOIN employee emp ON d.id=emp.deptId
                    LEFT JOIN admin a ON d.adminId=a.id
        WHERe d.id=#{id}
    
主键返回

​ 在插入一条记录后,得到数据库自动生成的这条记录的主键id

    
        insert into admin(account, password, sex)
        values (#{account}, #{password}, #{sex})
    
注解方式

​ 也可以通过注解的方式编写简单的sql

    @Select("select id,name from dept")
    List getName();
    
    @Test
    public void getDeptList1(){
        SqlSession sqlSession = MybatisUtil.openSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List deptName = mapper.getName();
        System.out.println(deptName);
    }
添加log4j日志组件

导入jar坐标

        
        
            log4j
            log4j
            1.2.17
        

在resources下导入log4j.properties文件

log4j.rootLogger = debug,stdout,D
#System out Console
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%p] %d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

#System out File
log4j.appender.D = org.apache.log4j.FileAppender
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = F://java project/logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ] -[%l] %m%n

在mybatis-config.xml中添加设置


单元测试

导入jar包

        
        
            junit
            junit
            4.12
            
            provided
        
懒加载

​ 对于关联查询,若不采用延迟加载策略,而是一次性将关联的从信息都查询出来,则在主信息比较多的情况下,会产生N+1问题,导致性能降低。比如在查询员工信息时,设置了关联查询部门信息,如不采用延迟加载策略,查询员工信息时就会把其部门信息全部查询出来,但我们却用不到,就会造成浪费。而懒加载就会让在需要部门信息的时候才执行查询部门的sql

    @Test
    public void getEmpById1(){
        SqlSession sqlSession = MybatisUtil.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmpById1(1);
        System.out.println(employee.getName());
        System.out.println(employee.getDept().getName());
        System.out.println(employee.getAdminUser().getAccount());
        sqlSession.commit();
        sqlSession.close();
    }

mybatis-config,xml中设置属性:

        
        
        
    Employee getEmpById1(int id);
    
        
        
        
        
            
        

        
            
        
    

    
        select * from admin where id=#{id}
    
    
        SELECT  emp.id,emp.name ename,emp.age,d.name dname,a.account
        FROM employee emp LEFT JOIN dept d ON emp.deptId=d.id
                          LEFT JOIN admin a ON emp.adminId=a.id
        
            
                emp.name=#{name}
            
            
                and emp.age=#{age}
            
        
    
trim

动态修改

​ trim prefix=“where” prefixOverrides=“and||or”

  • 当if有成立条件时,添加一个指定的前缀prefix (where)
  • 如果以prefixOverrides开头,可以覆盖掉关键字(and,or)
    
	
        SELECT  emp.id,emp.name ename,emp.age,d.name dname,a.account
        FROM employee emp LEFT JOIN dept d ON emp.deptId=d.id
                          LEFT JOIN admin a ON emp.adminId=a.id

        
            
                
                    and emp.name=#{name}
                
                
                
                    and emp.name='abc'
                
            
            
                
                    and emp.age=#{age}
                
            
        
    
set

​ 动态添加set关键字,删掉最后一个逗号

动态修改:传入的为空不改,不为空就修改

    
    @Test
    public void updateEmp(){
        Employee employee1 = new Employee();
                employee1.setId(1);
                employee1.setName("abc");
                employee1.setAge(20);
        Dept dept = new Dept();
             dept.setId(2);
                employee1.setDept(dept);

        SqlSession sqlSession = MybatisUtil.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        employeeMapper.updateEmp(employee1);
        sqlSession.commit();
        sqlSession.close();
    }
public interface EmployeeMapper {
    void updateEmp(Employee employee);
}
    
    
        update employee
        
            name=#{name},
            age=#{age},
            deptId=#{dept.id},
        
        where id=#{id}
    
foreach

​ 通过多个age查询时,就要对List中的元素进行遍历

在sql语句中是这样写的:

SELECT * FROM employee WHERe age IN(19,20)

所以使用foreach遍历时,就可以设定前缀、后缀和分隔符

  • item 表示集合中每一个元素进行迭代时的别名
  • index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置
  • open 表示该语句以什么开始
  • separator 表示在每次进行迭代之间以什么符号作为分隔符
  • close 表示以什么结束
  • collection 指定传来的类型(array、list …)
    
    @Test
    public void getEmpByAges(){
        List ageList = new ArrayList<>();
                ageList.add(18);
                ageList.add(19);
        SqlSession sqlSession = MybatisUtil.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        List employees = employeeMapper.getEmpByAges(ageList);
        System.out.println(employees);
        sqlSession.commit();
        sqlSession.close();
    }
public interface EmployeeMapper {
    List getEmpByAges(List ages);
}
    
    
        select * from employee
        where age in
        
            #{age}
        
    
特殊符号

使用案例:通过年龄段查询

    
    @Test
    public void getEmpByAgeInterval(){
        SqlSession sqlSession = MybatisUtil.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        List employees = employeeMapper.getEmpByAgeInterval(18,20);
        System.out.println(employees);
        sqlSession.commit();
        sqlSession.close();
    }
public interface EmployeeMapper {
    List getEmpByAgeInterval(@Param("min")int min,@Param("max")int max);
}
    
    
缓存
  • 缓存(cache)的作用是为了减去数据库的压力,提高数据库的性能。
  • 缓存实现的原理是从数据库中查询出来的对象在使用完后不要销毁,而是存储在内存(缓存)中,当再次需要获取该对象时,直接从内存(缓存)中直接获取,不再向数据库执行 select 语句,从而减少了对数据库的查询次数,因此提高了数据库的性能。
  • 缓存是使用 Map 集合缓存数据的
一级缓存


​ 一级缓存的作用域是同一个 SqlSession,在同一个 sqlSession 中两次执行相同的 sql 语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查 询,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的一级缓存也就不存在了。Mybatis 默认开启一级缓存

生命周期:

  • MyBatis 在开启一个数据库会话时,会创建一个新的 SqlSession 对象,SqlSession 对象中会有一个新的 Executor 对象。Executor 对象中持有一个新的 PerpetualCache 对象,如果 SqlSession 调用了 **close()**方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存将不可用。
  • 如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象中的数据,但是该对象仍可使用。
  • SqlSession 中执行了任何一个 update 操作(update()、delete()、insert()) ,都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用

​ 一级缓存时执行commit,close,增删改等操作,就会清空当前的一级缓存;当对SqlSession执行更新操作(update、delete、insert)后并执行commit时,不仅清空其自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)

二级缓存

​ 二级缓存是 SqlSessionFactory 级别的,根据 mapper 的 namespace 划分区域的,相同 namespace 的 mapper 查询的数据缓存在同一个区域,如果使用mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二级缓存区域是根据 mapper 划分

​ 每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。

​ sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区域,防止脏读

配置:

  1. 开启全局二级缓存配置,在mybatis-config.xml下加设置

    
    
  2. POJO 序列化 :将所有的 POJO ()类实现序列化接口 Java.io. Serializable

  3. 配置映射文件

    在 Mapper 映射文件中添加 cache,表示此 mapper 开启二级缓存。

    当 SqlSeesion 关闭时,会将数据存入到二级缓存

        
        
    
  4. 禁用缓存
    如测试sql语句性能时缓存会影响测试准确性 需要禁用在映射文件中:默认值是true useCache=”false”

  5. 刷新缓存
    在映射文件中:属性:flushCache=”true”刷新缓存,在查询语句中,默认值是false,在新增删除修改语句中,默认值是true(清空缓存)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458442.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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