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

MyBatis知识点

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

MyBatis知识点

MyBatis 三层架构
  • MyBatis 框架

​ MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。 MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来, 并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java
对象并返回。

  • Spring 框架

​ Spring 框架为了解决软件开发的复杂性而创建的。 Spring 使用的是基本的 JavaBean 来完成以前非常复杂的企业级开发。 Spring 解决了业务对象, 功能模块之间的耦合, 不仅在 javase,web 中使用,大部分 Java 应用都可以从 Spring 中受益。
​ Spring 是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。

  • SpringMVC框架

​ Spring MVC 属于 SpringframeWork 3.0 版本加入的一个模块,为 Spring 框架提供了构建 Web 应用程序的能力。现在可以 Spring 框架提供的 SpringMVC 模块实现 web 应用开发,在 web 项目中可以无缝使用 Spring 和 Spring MVC 框架。

JDBC回顾 编程实现
  • 查询数据代码实现
public void findStudent() { 
    Connection conn = null; 
    Statement stmt = null; 
    ResultSet rs = null; 
    try { 
        //注册 mysql 驱动 
        Class.forName("com.mysql.jdbc.Driver"); 
        //连接数据的基本信息 url,username,password 
        String url = "jdbc:mysql://localhost:3306/springdb"; 
        String username = "root"; 
        String password = ""; 
        //创建连接对象 
        conn = DriverManager.getConnection(url, username, password); 
        //保存查询结果 
        List stuList = new ArrayList<>(); 
        //创建 Statement, 用来执行 sql 语句 
        stmt = conn.createStatement(); 
        //执行查询,创建记录集, 
        rs = stmt.executeQuery("select * from student"); 
        while (rs.next()) { 
            Student stu = new Student(); 
            stu.setId(rs.getInt("id")); 
            stu.setName(rs.getString("name")); 
            stu.setAge(rs.getInt("age")); 
            //从数据库取出数据转为 Student 对象,封装到 List 集合 
            stuList.add(stu); 
        } 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } finally { 
        try { 
            //关闭资源 
            if (rs != null) ; 
            { 
                rs.close(); 
            } 
            if (stmt != null) { 
                stmt.close(); 
            } 
            if (conn != null) { 
                conn.close(); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
}
  • 使用JDBC的缺陷
    • 代码比较多,开发效率低
    • 需要关注Connection,Statement,ResultSet对象的创建和销毁
    • 对ResultSet查询的结果,需要自己手动封装成为List
    • 重复的代码比较多
    • 业务代码和数据库操作的代码混在一起,耦合度比较高
MyBatis 介绍

​ MyBatis 本是 apache 的一个开源项目 iBatis, 2010 年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis 。2013 年 11 月迁移到 Github。 iBATIS 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。iBATIS 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAOs)

JDBC解决的问题:

减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。 直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。

MyBatis 中编写的xml代码可以等价类比于JDBC编写的代码:

  1. 注册数据库的驱动,例如

    Class.forName(“com.mysql.jdbc.Driver”)
    
  2. 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象

  3. 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象

    List list = new ArrayLsit<>(); 
    ResultSet rs = state.executeQuery(“select * from student”); 
    while(rs.next){ 
        Student student = new Student(); 
        student.setName(rs.getString(“name”)); 
        student.setAge(rs.getInt(“age”)); 
        list.add(student); 
    } 
    
  4. 关闭资源

     ResultSet.close() , Statement.close() , Conenection.close()
    
入门案例
  • 创建student表
CREATE TABLE `student` ( 
    `id` int(11) NOT NULL , 
    `name` varchar(255) DEFAULT NULL, 
    `email` varchar(255) DEFAULT NULL, 
    `age` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  • 依赖

    org.mybatis
    mybatis
    3.5.1

# 数据库驱动

    mysql
    mysql-connector-java
    5.1.9

  • maven插件
 
     
         
            
            src/main/java 
            
                 
                ***.xml 
             
            false 
         
     

     
         
            maven-compiler-plugin 
            3.1 
             
                1.8 
                1.8 
             
         
     
 
  • StudentDao.xml
 
 
      	 
		 
            
        
    ,,,都可以使用 parameterType 指定类型
 
    delete from student where id=#{studentId} 
 

// 
    
 
    delete from student where id=#{studentId} 

参数传递
  • 1 个参数

    Dao 接口中方法的参数只有一个简单(基本数据)类型(java 基本类型和 String) ,占位符 #{ 任意字符 },和方法的参数名无关。

// 接口方法: 
Student selectById(int id); 

// Mapper.xml 文件: 
 
    select id,name,email,age from student where name=#{personName} or age=#{personAge} 
 
 
// 测试方法: 
@Test 
public void testSelectMultiParam(){ 
    List stuList = studentDao.selectMultiParam(" 李力",20); 
    stuList.forEach( stu -> System.out.println(stu)); 
}
  • 多个参数- 使用对象

    使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。 语法格式: #{property,javaType=java 中数据类型名,jdbcType=数据类型名称 } ,javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ property }。

    使用对象进行传递参数是我们在真实的项目开发中采用的方法

    // 设置对象进行封装需要查询的字段信息
    public class QueryParam { 
        private String queryName; 
        private int queryAge; 
        //set  ,get  方法 
    } 
    
    
    // 接口方法: 
    List selectMultiObject(QueryParam queryParam); 
     
    // mapper 文件: 
     
        select id,name,email,age from student 
        where name=#{queryName,javaType=string,jdbcType=VARCHAR} 
        or age =#{queryAge,javaType=int,jdbcType=INTEGER} 
     
     
    // 测试方法: 
    @Test 
    public void selectMultiObject(){ 
        QueryParam qp  = new QueryParam(); 
        qp.setQueryName("李力"); 
        qp.setQueryAge(20); 
        List stuList = studentDao.selectMultiObject(qp); 
        stuList.forEach( stu -> System.out.println(stu)); 
    } 
    
  • 多个参数- 按位置

参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}。

// 接口方法: 
List selectByNameAndAge(String name,int age); 
 
// mapper 文件 
 
    select id,name,email,age from student where name=#{myname} or age =#{myage} 
 
 
// 测试方法: 
@Test 
public void testSelectMultiMap(){ 
    Map data = new HashMap<>(); 
    data.put("myname"," 李力");// #{myname} 
    data.put("myage",20);    // #{myage} 
    List stuList = studentDao.selectMultiMap(data); 
    stuList.forEach( stu -> System.out.println(stu)); 
} 
  • # 和$

    ‘#’ 占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替
    sql 语句的“?” 。这样做更安全,更迅速,通常也是首选做法。

    // mapper 文件 
     
          select * from student where email=#{stuentEmail} 
     
     
    // 测试方法: 
    @Test 
    public void testFindStuent(){ 
        Student student1 = studentDao.findById(1002); 
        System.out.println("findById:"+student1); 
     
        Student student2 = studentDao.findByEmail("zhou@126.net"); 
        System.out.println("findByEmail:"+student2); 
    } 
     
    // 例 2:通用方法,使用不同列作为查询条件 
    // 接口方法: 
    Student findByDiffField(@Param("col") String colunName,@Param("cval") Object value); 
     
    // mapper 文件: 
     
        select count(*) from student 
     
     
    // 测试方法: 
    @Test 
    public void testRetunInt(){ 
        int count = studentDao.countStudent(); 
        System.out.println(" 学生总人数:"+ count); 
    } 
    
  • 对象类型

    // 接口方法: 
    public Student selectById(int id); 
     
    // mapper 文件: 
     
        select name,email from student where id = #{studentId} 
     
     
    // 测试方法: 
    @Test 
    public void testReturnMap(){ 
        Map retMap = studentDao.selectReturnMap(1002); 
        System.out.println(" 查询结果是 Map:"+retMap); 
    } 
    
  • ResultMap

    resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。 常用在列名和 java 对象属性名不一样的情况。

    使用方式:
    1.先定义 resultMap,指定列名和属性的对应关系。
    2.在中把 resultType 替换为 resultMap。

    // 接口方法: 
    List selectUseResultMap(QueryParam param); 
     
    // mapper 文件: 
          
     
         
         
         
         
         
         
     
     
     
     
        select id as stuId, name as stuName,age as stuAge 
        from student where  name=#{queryName} or age=#{queryAge} 
     
     
    // 4.测试方法 
    @Test 
    public void testSelectUseFieldAlias(){ 
        QueryParam param = new QueryParam(); 
        param.setQueryName(" 李力"); 
        param.setQueryAge(20); 
        List stuList = studentDao.selectUseFieldAlias(param); 
        stuList.forEach( stu -> System.out.println(stu)); 
    } 
    
  • 使用

    // 1. 接口方法 
    List selectUseDiffResultMap(QueryParam param); 
     
    // 2. mapper 文件: 
     
     
         
         
         
         
         
     
     
     
     
        select id,name,email,age from student 
        where name like #{studentName} 
     
     
    // 测试方法: 
    @Test 
    public void testSelectLikeOne(){ 
        String name="%力%"; 
        List stuList = studentDao.selectLikeFirst(name); 
        stuList.forEach( stu -> System.out.println(stu)); 
    } 
     
    ========================================
        
    // 例 2:mapper 文件中使用 like name "%" #{xxx} "%" 
    // 接口方法: 
    List selectLikeSecond(String name); 
     
    mapper 文件: 
     
        select id,name,email,age from student 
        where 1=1 
    	    
         
            and name = #{name} 
         
         
            and age > #{age} 
         
     
     
    // 测试方法: 
    @Test 
    public void testSelect() throws IOException { 
        Student param = new Student(); 
        param.setName(" 李力"); 
        param.setAge(18); 
     
        List studentList = studentDao.selectStudentIf(param); 
        studentList.forEach( stu -> System.out.println(stu)); 
    } 
    
  • 动态 SQL 之

    ​ 标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后的所有条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
    ​ 使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加where 子句。需要注意的是,第一个标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错 。
    ​ 语法: 其他动态 sql

    // 接口方法: 
    List selectStudentWhere(Student student); 
     
    // mapper 文件: 
     
        select id,name,email,age from student 
         
            where id in 
             
                #{stuid} 
             
         
     
     
    // 测试方法: 
    @Test 
    public void testSelectForList()  { 
        List list = new ArrayList<>(); 
        list.add(1002); 
        list.add(1005); 
        list.add(1006); 
     
        List studentList = studentDao.selectStudentForList(list); 
        studentList.forEach( stu -> System.out.println(stu)); 
    } 
    
  • 遍历 List< 对象类型>

    // 接口方法: 
    List selectStudentForList2(List stuList); 
     
    // mapper 文件: 
     
    
     
    // 测试方法: 
    @Test 
    public void testSelectSqlFragment()  { 
        List list = new ArrayList<>(); 
        Student s1 = new Student(); 
        s1.setId(1002); 
        list.add(s1); 
     
        s1 = new Student(); 
        s1.setId(1005); 
        list.add(s1); 
     
        List studentList = studentDao.selectStudentSqlFragment(list); 
        studentList.forEach( stu -> System.out.println(stu)); 
    } 
    
  • MyBatis 配置文件
    • 主配置文件

      // 之前项目中使用的 mybatis.xml 是主配置文件。 
      // 主配置文件特点: 
      // 1. xml 文件,需要在头部使用约束文件 
       
       
       
      // 2.根元素, 
       
      // 3.主要包含内容: 
      // ➢  定义别名 
      // ➢  数据源 
      // ➢  mapper 文件
      
    • dataSource 标签

      ​ Mybatis 中访问数据库,可以连接池技术,但它采用的是自己的连接池技术。在 Mybatis 的 mybatis-config.xml配置文件中,通过来实现 Mybatis 中连接池的配置。

      Mybatis 将数据源分为三类:
      UNPOOLED 不使用连接池的数据源
      POOLED 使用连接池的数据源
      JNDI 使用 JNDI 实现的数据源

      ​ 其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口, JNDI 和前面两个实现方式不同, 了解可以。

    • dataSource 配置

      // 在 MyBatis.xml 主配置文件,配置 dataSource: 
       
           
           
           
           
           
       
          
      // MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即: 
      // type=”POOLED” :MyBatis 会创建 PooledDataSource 实例  
      // type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例  
      // type=”JNDI” :MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
      
    • 事务

      • 默认需要手动提交事务

        Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback() . Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交、

        该标签用于指定MyBatis所使用的事务管理器。 MyBatis支持两种事务管理器类型: JDBC 与MANAGED。

        ➢ JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback()方法回滚。但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。

      • 自动提交事务

        设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。 有参数为 true,使用自动提交,可以修改 MyBatisUtil 的 getSqlSession()方法。session = factory.openSession(true); 再执行 insert 操作,无需执行session.commit(),事务是自动提交的。

    • 使用数据库属性配置文件

      为 了方便对数据库连接的管理, DB 连接四要素数据一般都是存放在一个专门的属性文件中的。 MyBatis主配置文件需要从这个属性文件中读取这些数据。

      • 在 classpath 路径下, 创建 properties 文件

      • 使用key指定值

         
             
             
             
             
             
        
        
      • typeAliases (类型别名)

        Mybatis 支持默认别名,我们也可以采用自定义别名方式来开发,主要使用在 mybatis.xml 主配置文件定义别名:

         
             
             
             
             
             
         
         
        # mapper.xml 文件,使用别名表示类型 
         
               select id,name,email,age from student 
         
        
    • mappers (映射器)

      使用相对于类路径的资源,从 classpath 路径查找文件
      例如:

      指定包下的所有 Dao 接口 如: 注意:此种方法要求 Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。
    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/322292.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

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

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