Mybatis

Mybatis的概述:

  • ORM(Object Relational Mapping) 持久层框架的佼佼者
  • 正真实现了SQL语句与Java代码的分离
  • 优秀的功能:动态SQL、缓存、插件=pageHelper等
  • 使用Mybatis需要导入:Mybatis的jar包和mysql的驱动:
        
        
            mysql
            mysql-connector-java
            5.1.47
        
        
        
            org.mybatis
            mybatis
            3.5.4
        

Mybatis入参处理

  • 传递单个参数的形式(mybatis会自动进行参数的赋值)
  • 传递多个参数(Mybatis会自动封装在Map集合中)
  • Collection、List、Array作为参数,封装为Map,但是有一定的规则
  • 多参数处理-封装POJO类:
    如果多个参数是我们业务逻辑的数据模型,我们就可以直接传入pojo
    Xml文件中:#{属性名} 取出传入的 pojo的属性值
  • 多参数处理-Map
    如果参数个数比较少,而且没有对应的Javabean,可以封装成Map
    Xml文件中:#{key} 取出map中对应的值
  • 多参数处理-@param的key。
    由于以上两种方式需要手动创建Map及对象,不简洁,可以使用@param注解,它可以明确指定封装参数时map的key。
    int del(@Param("key") int id);
    //取出
    #{key}

集合类型参数处理:

  • 当参数为Collection接口,转换为Map,Map的Key为collection
  • 如果参数类型为List接口的,除了collection的值外,list作为key(#{list[0]}或collection[0])
  • 如果参数为数组,也会转换为Map,Map的key为array

动态SQL——foreach:

  • foreach元素:
    • 特点:循环遍历集合,支持数组和List、Set ,对其提交遍历功能。
    • 应用:数据库中数据字典的内容,经常使用foreach元素确定查找
    • 常用属性:
    • 常用配置:
      • collection:数组名字
      • item:循环的对象的值
      • index:循环的item项,如果是map则是map的key
      • open和close:开始的字符和结尾的字符
      • separator:每次循环的分隔符

Mybatis高级知识点-批量插入:

使用传统JDBC进行数据的插入:

  • 传统的利用循坏进行插入,种方式存在严重效率问题,需要频繁获取Session,获取连接
  • 使用批处理,代码和SQL的耦合,代码量较大。
  • 解决:使用MyBatis支持批量插入的配置和语法

MyBatis对于批量插入的支持:

方式:
  • 1、借助foreach标签使用 insert into table values()

	insert into goods values
	
		(#{list.id},#{list.name},#{list.price})
	

  • 2、借助MySQL数据库连接属性allowMultiQueries=true
    jdbc.url=jdbc:mysql://localhost:3306/mylstu?allowMultiQueries=true

	
		insert into goods values
		(#{list.id},#{list.name},#{list.price})
	

基于SqlSession的ExecutorType进行批量添加:

前两种都是字符串拼接的,而mysql的底层逗号、分号实际拼接的是一个很长的字符串,其工作效率是很低的。

  • Executor
    Mybatis_第1张图片
小总结:
  • 1、’MySQL下批量保存的两种方式,建议使用第一种
  • 2、可以借助Executor的Batch批量添加,可与Spring框架整合。

MyBatis拦截器实现分页:

Mybatis四大对象:

  • Mybatis核心对象:
    • ParameterHandler:处理SQL的参数对象
    • ResultSetHandler:处理SQL的返回结果集
    • StatementHandler:数据库的处理对象,用于执行SQL语句
    • Executor:Mybatis的执行器,用于执行增删改操作

Mybatis插件原理:

  • Mybatis的插件借助于责任链的模式进行对拦截器的处理
  • 使用动态代理对目标对象进行包装,达到拦截的目的
  • 作用于Mybatis的作用域对象之上

Mybatis插件接口-Interceptor:

  • Intercept方法,插件的核心方法
  • 使用plugin方法,生成target的代理对象
  • setProperties方法,配置所需参数
插件开发过程:

1、确定拦截的签名
2、实现拦截方法
3、配置和运行

  • 1、自定义插件:
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import java.sql.Statement;
import java.util.Properties;
/*
* Interceptor是apache下的接口
* @Intercepts:插件签名,告诉mybatis单线插件用来拦截那个对象的那个方法
* type:拦截的类或接口
* method:拦截的方法
* args:拦截被方法中的参数
* 注意:注解中{}表示数组
* */
@Intercepts({@Signature(type= ResultSetHandler.class,method ="handleResultSets",args = Statement.class)})
public class MyFirstInterceptor implements Interceptor {
    //拦截目标对象的目标方法的
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("拦截的对象 :"+invocation.getTarget());
        System.out.println("拦截被方法 :"+invocation.getMethod());
        System.out.println("拦截被方法中的参数 :"+invocation.getArgs());
        Object object=invocation.proceed();
        return object;
    }
    //包装目标对象,为目标对象创建代理对象的
    public Object plugin(Object target) {
        System.out.println("将要包装的对象 :"+target);
        return Plugin.wrap(target,this);
    }
    //插件初始化的
    public void setProperties(Properties properties) {
        System.out.println("插件配置的初始化 :"+properties);
    }
}
  • 2、xml文件中配置插件:
    
    
        
            
            
        
    
  • 3、 签名,在自定义插件中(@Intercepts:插件签名)
分页原理:
  • 分页的分类:内存分页和物理分页(内存分页是一次性查出数据,后处理)
  • MySQL中实现分页的关键字(LIMIT):
select *from `order` LIMIT 0,10 //0:从0开始;10:10行数据

  • 分页原理-规律:
    • 开始记录索引的规律(当前页-1)*每页的条数
    • 一共有多少页:总记录%条数==0 ? 总记录/条数: +1;
  • 分页原理-三个参数:
    • 当前页(getPageNum())
    • 每页的条数(getPageSize())
    • 总记录数(getTotal())
  • 最好用一个类管理分页信息:
package com.imooc.shop.utils;

// 分页实体
public class Pager {
    // 1.当前页码
    private int pageIndex;
    // 2.一页需要展示多少条数据
    private int pageSize = 3 ;
    // 3.当前条件下总的数据量
    private int totalCount ;
    // 4.总共可以分多少页
    private int totalPages ;

    public int getPageIndex() {
        // 取页码的时候,做一些判断
        pageIndex = pageIndex <= 0 ? 1 : pageIndex ;
        // 判断页码是否越界 了
        pageIndex = pageIndex>= getTotalPages() ? getTotalPages(): pageIndex;
        return pageIndex;
    }

    public void setPageIndex(int pageIndex) {
        this.pageIndex = pageIndex;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public int getTotalPages() {
        // 总页数
        // 根据总数据量和每页最多展示多少来确定的
        // 10条数据 3 -> 4页
        // 9条数据  3  -> 3页
        return (this.getTotalCount() -1 )  / this.getPageSize() + 1;
    }

    // 分页的第一个参数
    public int getFirstParam(){
        return (this.getPageIndex()  -1)*this.getPageSize();
    }


}

PageHelper分页插件的使用:

可见官网:添加链接描述

  • 1、下载PageHelper,在这里导入插件
        
        
            com.github.pagehelper
            pagehelper
            5.1.10
        
实例:

1、mybatis接口:

public interface orderDao {
    int deleteByPrimaryKey(String id);

    int insert(Order record);

    int insertSelective(Order record);

    Order selectByPrimaryKey(String id);

    List selectByPrimaryKeylist();

    int updateByPrimaryKeySelective(Order record);

    int updateByPrimaryKey(Order record);
}

2、Mybatis配置接口:




  
    
    
    
    
    
    
    
    
    
    
    
  
  
    id, gid, num, price, up_date, hair_date, confirm_date, consignee, consignee_Tel, 
    consignee_address, state
  
  
  
    delete from `order`
    where id = #{id,jdbcType=CHAR}
  
  
    insert into `order` (id, gid, num, price,
      up_date, hair_date, confirm_date, 
      consignee, consignee_Tel, consignee_address, 
      state)
    values (#{id,jdbcType=CHAR}, #{gid,jdbcType=CHAR}, #{num,jdbcType=INTEGER}, #{price,jdbcType=DOUBLE}, 
      #{upDate,jdbcType=TIMESTAMP}, #{hairDate,jdbcType=TIMESTAMP}, #{confirmDate,jdbcType=TIMESTAMP}, 
      #{consignee,jdbcType=VARCHAR}, #{consigneeTel,jdbcType=CHAR}, #{consigneeAddress,jdbcType=VARCHAR}, 
      #{state,jdbcType=VARCHAR})
  
  
    insert into `order`
    
      
        id,
      
      
        gid,
      
      
        num,
      
      
        price,
      
      
        up_date,
      
      
        hair_date,
      
      
        confirm_date,
      
      
        consignee,
      
      
        consignee_Tel,
      
      
        consignee_address,
      
      
        state,
      
    
    
      
        #{id,jdbcType=CHAR},
      
      
        #{gid,jdbcType=CHAR},
      
      
        #{num,jdbcType=INTEGER},
      
      
        #{price,jdbcType=DOUBLE},
      
      
        #{upDate,jdbcType=TIMESTAMP},
      
      
        #{hairDate,jdbcType=TIMESTAMP},
      
      
        #{confirmDate,jdbcType=TIMESTAMP},
      
      
        #{consignee,jdbcType=VARCHAR},
      
      
        #{consigneeTel,jdbcType=CHAR},
      
      
        #{consigneeAddress,jdbcType=VARCHAR},
      
      
        #{state,jdbcType=VARCHAR},
      
    
  
  
    update `order`
    
      
        gid = #{gid,jdbcType=CHAR},
      
      
        num = #{num,jdbcType=INTEGER},
      
      
        price = #{price,jdbcType=DOUBLE},
      
      
        up_date = #{upDate,jdbcType=TIMESTAMP},
      
      
        hair_date = #{hairDate,jdbcType=TIMESTAMP},
      
      
        confirm_date = #{confirmDate,jdbcType=TIMESTAMP},
      
      
        consignee = #{consignee,jdbcType=VARCHAR},
      
      
        consignee_Tel = #{consigneeTel,jdbcType=CHAR},
      
      
        consignee_address = #{consigneeAddress,jdbcType=VARCHAR},
      
      
        state = #{state,jdbcType=VARCHAR},
      
    
    where id = #{id,jdbcType=CHAR}
  
  
    update `order`
    set gid = #{gid,jdbcType=CHAR},
      num = #{num,jdbcType=INTEGER},
      price = #{price,jdbcType=DOUBLE},
      up_date = #{upDate,jdbcType=TIMESTAMP},
      hair_date = #{hairDate,jdbcType=TIMESTAMP},
      confirm_date = #{confirmDate,jdbcType=TIMESTAMP},
      consignee = #{consignee,jdbcType=VARCHAR},
      consignee_Tel = #{consigneeTel,jdbcType=CHAR},
      consignee_address = #{consigneeAddress,jdbcType=VARCHAR},
      state = #{state,jdbcType=VARCHAR}
    where id = #{id,jdbcType=CHAR}
  
  

3、Mybatis配置文件:





    
    
    
    
        
        
        
        
    
    
    
        
    
    
    
        
    

    
    
        
            
            
                
                
                
                
            
        
    
    
    
        
        
        
    
   
    
    
        
    

4、调用:

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ico.mybatis.bean.Order;
import ico.mybatis.orderDao;
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.Test;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

public class TestUser {
    //获取连接
    public static SqlSessionFactory sqlSessionFactory = null;
    public static SqlSessionFactory getSqlSessionFactory() {
        if (sqlSessionFactory == null) {
            String resource = "mybatis-config.xml";
            try {
                Reader reader = Resources.getResourceAsReader(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sqlSessionFactory;
    }
    @Test
    public  void testcollection(){
        SqlSession sqlSession=this.getSqlSessionFactory().openSession();
        orderDao daom=sqlSession.getMapper(orderDao.class);
        Page page = PageHelper.startPage(1, 10);//PageHelper会拦截execute到达分页
        List pages = daom.selectByPrimaryKeylist();
        PageInfo pageInfo=new PageInfo(pages,5);
        for (Order bean:pages) {
            System.out.println(bean.toString());
        }
        System.out.println(page.getPageNum());//当前页码
        System.out.println(page.getTotal());//总条数
        System.out.println(page.getPageSize());//每一页显示的数据
        System.out.println(pageInfo.isIsFirstPage());//通过PageInfo对象来判断是否位第一页
        System.out.println(pageInfo.getPages());//通过PageInfo对象来获取页数
        int[] nums = pageInfo.getNavigatepageNums();//获取有多少个页码
        for (int i=0;i 
  

拦截器进行分页总结

  • 遵循插件尽量不使用的原则,因为会修改底层设计
  • 插件是生成的层层代理对象的责任链模式,使用反射机制实现
  • 插件的编写要考虑全面,特别是多个插件层层代理的时候。

你可能感兴趣的:(Java框架)