Mybatis框架复习&&整合Spring(二)

log4j
 
打印程序运行的日志,我们可以通过日志清楚的看到程序底层运行的一些逻辑顺序,类似于debug
  1. 引入jar
    <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>2.13.3</version>
    </dependency>
  2. 导入log4j配置文件
  3. Mybatis配置文件中,在全局配置<settings>中开启sql日志功能
    <setting name = "logImpl" value = "STDOUT_LOGGING" />

Mybatis 缓存
 
  1. 一级缓存
    Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只是开启了一级缓存(一级缓存是相对于同一个SqlSession而言)在sql和参数完全一致的情况下,使用同一个sqlsession对象调用同一个Mapper的方法,只会执行一次Sql ,因为使用Sqlsession第一次查询后,Mybatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有设置超时时间的情况下,SqlSession都只会读取当前缓存的数据,而不会再次发送sql到数据库

    如果不是一个Sqlsession对象,因为不同Sqlsession都是相互隔离的,所以一级缓存失效

    测试一级缓存:此时不是同一个Sqlsession,通过log4j日志可以看出,生成了2条sql语句
    @Test public void findById() throws IOException { 
        //通过流,将核心配置文件读取出来 
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 
        //通过核心配置文件创建会话工厂 
        SqlSessionFactory factor = new SqlSessionFactoryBuilder().build(inputStream); 
        //通过会话工厂创建会话 
        SqlSession sqlSession = factor.openSession(); 
        User user = sqlSession.selectOne("test.findById",8); 
        SqlSession sqlSession2 = factor.openSession(); 
        User user1 = sqlSession2.selectOne("test.findById",8); 
        System.out.println(user==user1); // false 
    }
    此时,是同一个 Sqlsession, 只生成了一条 sql 语句
    @Test public void findById() throws IOException { 
        //通过流,将核心配置文件读取出来 
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 
        //通过核心配置文件创建会话工厂 
        SqlSessionFactory factor = new SqlSessionFactoryBuilder().build(inputStream); 
        //通过会话工厂创建会话 
        SqlSession sqlSession = factor.openSession(); 
        User user = sqlSession.selectOne("test.findById",8); 
        User user1 = sqlSession.selectOne("test.findById",8); 
        System.out.println(user==user1); 
    }
    一级缓存声明周期,什么时候缓存失效:
           mybatis开启一个数据库会话时,会创建一个新的Sqlsession对象,Sqlsession对象中有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache缓存对象,当会话结束时,Sqlsession对象及其内部所有一并释放,缓存也就清空调用sqlsession.close()调用了sqlSession.clearCache() 在sqlsession中执行了任何一个update操作(update,delete,insert)都会清空缓存 spring整合mybatis后,spring默认继承的不是 DefaultSqlSession,而是SqlSessionTemplate,spring默认每次调用一次方法后,都会执行sqlsession.close(),也就是spring整合Mybatis后一级缓存失效
     
  2. 二级缓存
    Mybatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用性能Mybatis的二级缓存是指mapper映射文件,二级缓存的作用域是同一个namespace下mapper映射文件的内容,多个sqlsession共享
     

     

    二级缓存默认是不开启的,如果想开启二级缓存,需要进行配置实现二级缓存的时候,Mybatis要求返回的POJO必须是可序列化的,实现序列化接口
     
    配置方法很简单,只需要在映射xml(mapper.xml中)文件配置开启缓存即可
    映射语句文件中所有select语句会被缓存
    映射语句文件中所有insert,updatte,delete都会刷新清空缓存
    缓存会使用默认的 Least Recently Used(LRU,最近最少使用的)算法来回收
     
    实体类实现序列化接口 - 由于二级缓存不一定都是存储到内存中,也可以存储到外部,所以需要加序列化
    public class User implements Serializable
    在映射文件中开启二级缓存 (mapper.xml )
    <mapper namespace = "com.zb.mapper.UserMapper" >
    <!--
    eviction :代表混村回收策略 LRU- 最近最少使用 FIFO- 先进先出
    flushInterval :刷新缓存间隔时间 单位是毫秒
    readOnly :只读,缓存只能读取不能被修改
    size :表示缓存可以存储多少各对象,不宜过大,过大可能导致内存溢出
    -->
    <cache eviction = "LRU" flushInterval = "100000" readOnly = "true" size = "1024" ></cache>
    mybatis 全局设置中,开启二级缓存
    <settings>
    <!-- 开启二级缓存 -->
    <setting name = "cacheEnabled" value = "true" ></setting>
    </settings>
    测试 此时 Spring 整合 Mybatis 由于开启了二级缓存,是全局级别缓存而不是sqlsession会话级别,此时可以通过 log4j 日志看到, sql 语句只生成了一次
     
    @Test public void findById(){ 
        User user = userMapper.findById(10); 
        User user2 = userMapper.findById(10); 
        System.out.println(user==user2); //true 
    }

     


Mybatis 逆向工程
 
  1. 概述
          我们在使用mybatis时,程序员需要自己在mapper.xml中编写sql语句,自己编写实体类,编写接口。mybatis官方提供理想工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java/mapper.xml/pojo...),可以让程序员将更多的经历放
    在繁杂的业务逻辑上
          在企业实际开发中,根据不同业务需求吧,逆向工程也经常使用之所以强调单表两个字,时因为Mybatis你想工程生成的mapper所进行的操作都是针对单表的,也许你觉得比较鸡肋,但是在某些项目中很少使用多表关联查询,所以作用还是很大的
  2. 入门
    1. 下载逆向工程 jar包 或者可以直接 maven下载                                                                                                                   https://github.com/mybatis/generator/releases                                                                                                                
       <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator</artifactId>
            <version>1.4.0</version>
          </dependency>
          <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.4.0</version>
         </dependency>

       

    2. 代码的生成
      代码生成一共有三种方式可以帮助我们自动生成 eclipes 中插件 / 利用Maven插件生成 / 使用 java 程序生成
      创建普通的 java 项目 用于生成文件,生成后我们在粘贴到项目中
      引入下载好的 jar 包和 mysql 驱动
       
      创建生成代码 :
       
      package com.zb.NXproject;
      
      import org.mybatis.generator.api.MyBatisGenerator;
      import org.mybatis.generator.config.Configuration;
      import org.mybatis.generator.config.xml.ConfigurationParser;
      import org.mybatis.generator.internal.DefaultShellCallback;
      
      import java.io.File;
      import java.util.ArrayList;
      import java.util.List;
      
      public class GeneratorSqlmap {
          public void generator() throws Exception {
              List<String> warnings = new ArrayList<String>();
              boolean overwrite = true;
              // 指定配置文件
              File configFile = new File("./config/NXProject/generatorConfig.xml");
              ConfigurationParser cp = new ConfigurationParser(warnings);
              Configuration config = cp.parseConfiguration(configFile);
              DefaultShellCallback callback = new DefaultShellCallback(overwrite);
              MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
              myBatisGenerator.generate(null);
          }
      
          // 执行main方法以生成代码
          public static void main(String[] args) {
              try {
                  GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
                  generatorSqlmap.generator();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
      

       

    3. 创建配置文件 generatorConfig.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
      
      <generatorConfiguration>
          <context id="DB2Tables" targetRuntime="MyBatis3">
              <commentGenerator>
                  <!-- 是否去除自动生成的注释 -->
                  <property name="suppressAllComments" value="true"/>
              </commentGenerator>
              <!-- Mysql数据库连接的信息:驱动类、连接地址、用户名、密码 -->
              <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                              connectionURL="jdbc:mysql://localhost:3306/ums"
                              userId="root"
                              password="root">
              </jdbcConnection>
              <!-- Oracle数据库
                  <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
                      connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
                      userId="yycg"
                      password="yycg">
                  </jdbcConnection>
              -->
      
              <!-- 默认为false,把JDBC DECIMAL 和NUMERIC类型解析为Integer,为true时
              把JDBC DECIMAL 和NUMERIC类型解析为java.math.BigDecimal -->
              <javaTypeResolver >
                  <property name="forceBigDecimals" value="false" />
              </javaTypeResolver>
      
              <!-- targetProject:生成POJO类的位置 -->
              <javaModelGenerator targetPackage="com.zb.pojo" targetProject=".\src">
                  <!-- enableSubPackages:是否让schema作为包的后缀 -->
                  <property name="enableSubPackages" value="false" />
                  <!-- 从数据库返回的值被清理前后的空格 -->
                  <property name="trimStrings" value="true" />
              </javaModelGenerator>
      
              <!-- targetProject:mapper映射文件生成的位置 -->
              <sqlMapGenerator targetPackage="cn.zb.mapper"  targetProject=".\src">
                  <!-- enableSubPackages:是否让schema作为包的后缀 -->
                  <property name="enableSubPackages" value="false" />
              </sqlMapGenerator>
      
              <!-- targetProject:mapper接口生成的的位置 -->
              <javaClientGenerator type="XMLMAPPER" targetPackage="cn.zb.mapper"  targetProject=".\src">
                  <!-- enableSubPackages:是否让schema作为包的后缀 -->
                  <property name="enableSubPackages" value="false" />
              </javaClientGenerator>
      
              <!-- 指定数据表 -->
              <table schema="" tableName="user"></table>
      
      
              <!-- 有些表的字段需要指定java类型
              <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
                <property name="useActualColumnNames" value="true"/>
                <generatedKey column="ID" sqlStatement="DB2" identity="true" />
                <columnOverride column="DATE_FIELD" property="startDate" />
                <ignoreColumn column="FRED" />
                <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
              </table> -->
      
          </context>
      </generatorConfiguration>
      

      配置完成后,运行创建生成代码中的Main方法,启动逆向工程 

      除了生成常规的 pojo 之外,还生成了用于设置条件的 xxxExample, 里面封装了很多查询条件
  3. 使用                                                                                                                                                                                                 将我们自动生成的代码,放到我们自己的项目对应路径中           
    1. 查询:不足支出,不能指定查询的列,只能够查询所有列
      public class TestNX {
          private ClassPathXmlApplicationContext ac;
          private UserMapper userMapper;
          private DepartmentMapper departmentMapper;
      
          @Before
          public void doBefore(){
              ac=new ClassPathXmlApplicationContext("spring-config.xml");
              userMapper=ac.getBean("userMapper",UserMapper.class);
              departmentMapper=ac.getBean("departmentMapper",DepartmentMapper.class);
          }
      
          @Test
          public void TestNXSelect(){
              //创建用于设置条件的对象
              DepartmentExample de=new DepartmentExample();
              DepartmentExample.Criteria criteria=de.createCriteria();
              criteria.andIdBetween(2,3);
              //查询方法一:根据条件查询
              List<Department> list=departmentMapper.selectByExample(de);
              System.out.println(list);
              //查询方法二:根据主键查询
              Department department=departmentMapper.selectByPrimaryKey(1);
              System.out.println(department);
          }
      
      
          @After
          public void doAfter(){
              ac.close();
          }
      }
      
    2. 插入
      插入操作很简单,只有两个方法,方法传入的参数都是 pojo 类型,返回值也是受影响的行数
      insert 会插入所有信息,如果传入的对象某一属性为空,则出入空,如果数据库中设置了默认值,默认值就失效了
      insertSelective 只会插入有数据的属性,对于为空的属性,不予理会,这样不会覆盖数据库中的默认值
      @Test
          public void TestNXInsert(){
              Department department=new Department();
              departmentMapper.insert(department);
              departmentMapper.insertSelective(department);
          }

       

    3. 删除也是有两个方法,根据主键删除 / 根据条件删除
      @Test
          public void TestNXDelete(){
              DepartmentExample de=new DepartmentExample();
              DepartmentExample.Criteria criteria = de.createCriteria();
              criteria.andNameEqualTo("人力资源部");
              //根据条件删除
              departmentMapper.deleteByExample(de);
              //根据主键删除
              departmentMapper.deleteByPrimaryKey(1);
          }
    4. 更新 更新的方法一共有 4个,我们可以将这4个方法分为两组去理解
      根据特定限制条件更新 xxxByExample
      updateByExample :根据特定的限制条件进行更新,除了 text 类型的所有列
      updateByExampleSelective :根据特定的限制条件更新所有列
      根据主键 ID 更新
      updateByPrimaryKey :通过 id 进行更新,除了 text 类型的所有列
      updateByPrimaryKeySelective: 通过 id 进行更新所有列

Mybatis 使用注解实现增删改查
 
在我们 sql 语句比较简单时我们可以直接在注解中写 sql 语句
在抽象方法上添加注解,在测试类直接调用方法即可,无需在 mapper.xml 映射文件中配置节点,适用于简单的增删改查
 
@Delete("delete from user where id = #{id}")
Integer deleteById(Integer id);
@Select("select * from user where id = #{id}")
User findById(Integer id);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值