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

Mybatis

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

Mybatis

一、Mybatis的简介 1.1.Mybatis的简介
  1. MyBatis 是支持定制化 SQL、存储过程以及高级
    映射的优秀的持久层框架。
  2. MyBatis 避免了几乎所有的 JDBC 代码和手动设
    置参数以及获取结果集。
  3. MyBatis可以使用简单的XML或注解用于配置和原
    始映射,将接口和Java的POJO(Plain Old Java
    Objects,普通的Java对象)映射成数据库中的记
    录。
  4. 原是Apache的一个开源项目iBatis, 2010年6月这
    个项目由Apache Software Foundation 迁移到了
    Google Code,随着开发团队转投Google Code
    旗下, iBatis3.x正式更名为MyBatis ,代码于
    2013年11月迁移到Github(下载地址见后)。
  5. iBatis一词来源于“internet”和“abatis”的组合,是
    一个基于Java的持久层框架。 iBatis提供的持久
    层框架包括SQL Maps和Data Access Objects
    (DAO)。
1.2.为什么要使用MyBatis?
  1. MyBatis是一个半自动化的持久化层框架。
  2. JDBC
    – a. SQL夹在Java代码块里,耦合度高导致硬编码内伤。
    – b. 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见。
  3. Hibernate和JPA
    – a. 长难复杂SQL,对于Hibernate而言处理也不容易。
    – b. 内部自动生产的SQL,不容易做特殊优化。
    – c. 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。
    导致数据库性能下降。
  4. 对开发人员而言,核心sql还是需要自己优化。
  5. sql和java编码分开,功能边界清晰,一个专注业务、
    一个专注数据。
1.3.去哪里找MyBatis?

https://mybatis.org/mybatis-3/zh/index.html

二、MyBatis-HelloWorld 2.1.创建一张测试表

创建表名为tbl_employee

   CREATE TABLE `tbl_employee` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `last_name` VARCHAr(255) COLLATE utf8_german2_ci DEFAULT NULL,
  `gender` VARCHAr(10) COLLATE utf8_german2_ci DEFAULT NULL,
  `email` VARCHAr(255) COLLATE utf8_german2_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) 
2.2.创建对应的javaBean

创建在com.tedu.java.pojo目录下
![在

package com.tedu.pojo;

public class Employee {
	
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", lastName=" + lastName + ", email="
				+ email + ", gender=" + gender + "]";
	}
}

2.3.创建mybatis配置文件,sql映射文件

a. 创建全局配置文件




	
		
			
			
				
				
				
				
			
		
	
	
	
		
	

b. 创建sql映射文件





	
		select id,last_name lastName,email,gender from tbl_employee where id = #{id}
	

c.创建dao接口

package com.tedu.dao;

import com.tedu.pojo.Employee;

public interface EmployeeMapper {
    public Employee getEmployeeById(Integer id);
}
三、MyBatis-全局配置文件
  • 1、创建MyBatis全局配置文件
    – MyBatis 的全局配置文件包含了影响 MyBatis 行为甚深
    的设置(settings)和属性(properties)信息、如数据
    库连接池信息等。指导着MyBatis进行工作。我们可以
    参照官方文件的配置示例。
  • 2、创建SQL映射文件
    – 映射文件的作用就相当于是定义Dao接口的实现类如何
    工作。这也是我们使用MyBatis时编写的最多的文件。
  • 3、测试
package com.tedu.test;

import com.tedu.dao.EmployeeMapper;
import com.tedu.pojo.Employee;
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.InputStream;


public class MyBatisTest {
    
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test2() throws IOException {
        //1.获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        //2.获取sqlSession对象
        SqlSession openSession = sqlSessionFactory.openSession();
        //3.取货接口的实现类
        try {
            //会为接口自动创建一个代理对象
            EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
            Employee employee = mapper.getEmployeeById(1);
            System.out.println(employee);
        } finally {
            //资源的关闭
            openSession.close();
        }
    }
}

注:

  1. SqlSession 的实例不是线程安全的,因此是不能
    被共享的。
  2. SqlSession每次使用完成后需要正确关闭,这个
    关闭操作是必须的。
  3. SqlSession可以直接调用方法的id进行数据库操
    作,但是我们一般还是推荐使用SqlSession获取
    到Dao接口的代理类,执行代理对象的方法,可
    以更安全的进行类型检查操作。
3.1.Mybatis配置文件

MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。文档的顶层结构如下:
configuration 配置:
• properties 属性
• settings 设置
• typeAliases 类型命名
• typeHandlers 类型处理器
• objectFactory 对象工厂
• plugins 插件
• environments 环境
• environment 环境变量
• transactionManager 事务管理器
• dataSource 数据源
• databaseIdProvider 数据库厂商标识
• mappers 映射器

3.2.在Idea中引入XML的dtd约束文件,方便编写XML的时候有提示

3.3.properties属性

mybatis可以使用properties来引入外部properties配置文件的内容:
resource,引入类路径下的资源
url 引入网络中的资源


jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root




注:

  1. 如果属性在不只一个地方进行了配置,那么 MyBatis 将按
    照下面的顺序来加载:
    – 在 properties 元素体内指定的属性首先被读取。
    – 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根
    据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
    – 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
3.4.settings设置
设置参数描述有效值默认值
cacheEnabled该配置影响着所有的映射器中配置的缓存的全局开关true falsetrue
lazyLoadingEnabled延迟加载的全局开关,当开启时,所有关联的对象都会延迟加载。特定关联关系中可以通过设置fetchType属性来覆盖该项的开关状态true falsefalse
useColumnLabel使用列标签来代替列名。不同的驱动会有不同的变现true falsetrue
defaultStatementTimeOut设置超时时间,它决定驱动等待数据库响应的秒数Any positive integernot set null
mapUnderScoreToCamelCase是否自动开启驼峰命名规则映射,即从经典的数据库列名到java类列属性的映射true falsefalse
	
		
	
3.5.typeAliases别名处理器
  1. 类型别名是为 Java 类型设置一个短的名字,可以方便我们
    引用某个类。

        
        
    
  1. 类很多的情况下,可以批量设置别名这个包下的每一个类
    创建一个默认的别名,就是简单类名小写。

        
    
  1. 也可以使用@Alias注解为其指定一个别名
@Alias("Emp")
public class Employee {
	}

注:值得注意的是,MyBatis已经为许多常见的 Java 类型内建
了相应的类型别名。它们都是大小写不敏感的,我们在起
别名的时候千万不要占用已有的别名。

别名映射的类型别名映射的类型别名映射的类型
_bytebytestringStringdateDate
_longlongbyteBytedecimalBigDecimal
_shortshortlongLongbigdecimalBigDecimal
_intintshortShortobjectObject
_integerintegerintIntegermapMap
_doubledoubleintegerIntegerhashmapHashMap
_floatfloatdoubleDoublelistList
_booleanbooleanfloatFloatarraylistArrayList
booleanBooleancollectionCollectioniteratorIterator
3.6.typeHandlers类型处理器

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型 。

类型处理器Java 类型JDBC 类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的NUMERIC 或BYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的NUMERIC 或SHORT INTEGER
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的NUMERIC 或INTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的NUMERIC 或LONG INTEGER
FloatTypeHandlerjava.lang.Float, float数据库兼容的NUMERIC 或FLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的NUMERIC 或DOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的NUMERIC 或DECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
3.7.日期类型的处理
  • 日期和时间的处理,JDK1.8以前一直是个头疼的
    问题。我们通常使用JSR310规范领导者Stephen
    Colebourne创建的Joda-Time来操作。1.8已经实
    现全部的JSR310规范了。
  • 日期时间处理上,我们可以使用MyBatis基于
    JSR310(Date and Time API)编写的各种日期
    时间类型处理器。
  • MyBatis3.4以前的版本需要我们手动注册这些处
    理器,以后的版本都是自动注册的。
3.8.自定义类型处理器
  • 我们可以重写类型处理器或创建自己的类型处理
    器来处理不支持的或非标准的类型。
  • 步骤:
    1. 实现org.apache.ibatis.type.TypeHandler接口或
      者继承org.apache.ibatis.type.baseTypeHandler。
    2. 指定其映射某个JDBC类型(可选操作)。
    3. 在mybatis全局配置文件中注册。
3.9.environments环境
  1. MyBatis可以配置多种环境,比如开发、测试和生
    产环境需要有不同的配置。
  2. 每种环境使用一个environment标签进行配置并指
    定唯一标识符。
  3. 可以通过environments标签中的default属性指定
    一个环境的标识符来快速的切换环境。
  4. environment-指定具体环境:
    • id:指定当前环境的唯一标识
    • transactionManager、和dataSource都必须有

		
			
			
				
				
				
				
			
		
		
			
			
		
	
3.9.1.transactionManager
  1. type: JDBC | MANAGED | 自定义
    • JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数
      据源得到的连接来管理事务范围。
      JdbcTransactionFactory
    • MANAGED:不提交或回滚一个连接、让容器来管理
      事务的整个生命周期(比如 JEE 应用服务器的上下
      文)。 ManagedTransactionFactory
    • 自定义:实现TransactionFactory接口,type=全类名/
      别名
3.9.2.dataSource
  1. type: UNPOOLED | POOLED | JNDI | 自定义
    - UNPOOLED:不使用连接池,UnpooledDataSourceFactory
    - POOLED:使用连接池, PooledDataSourceFactory
    - JNDI: 在EJB 或应用服务器这类容器中查找指定的数
    据源
    - 自定义:实现DataSourceFactory接口,定义数据源的
    获取方式。
  2. 实际开发中我们使用Spring管理数据源,并进行
    事务控制的配置来覆盖上述配置。
3.10.databaseIdProvider环境
  1. MyBatis 可以根据不同的数据库厂商执行不同的语句。
	
	
		
		
		
		
	
	- Type: DB_VENDOR
	- 使用MyBatis提供的VendorDatabaseIdProvider解析数据库厂商标识。也可以实现DatabaseIdProvider接口来自定义。
	- Property-name:数据库厂商标识
	- Property-value:为标识起一个别名,方便SQL语句使用databaseId属性引用
	
    select * from tbl_employee where id=#{id}

  1. 多个参数
    – 任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,0,1…,值就是参数的值。
public Employee getEmpByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);


        select * from tbl_employee where id=#{id} and last_name=#{lastName}
    
  1. POJO
    – 当这些参数属于我们业务POJO时,我们直接传递POJO。
public Long addEmployee(Employee employee);



    insert into tbl_employee (last_name,email,gender) values (#{lastName},#{email},#{gender})


  1. Map
    – 我们也可以封装多个参数为map,直接传递。
public Employee getEmpByMap(Map map);

    select  * from tbl_employee where id=#{id}

4.7.id&result

id 和 result 映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的属性或字段。

属性解释
property映射到列结果的字段或属性。例如:“username” 或者"address.street.number"。
column数据表的列名。通常和resultSet.getString(columnName)的返回值一致。
javaType一个Java类的完全限定名,或一个类型别名。如果映射到一个JavaBean,Mybatis通常可以判定类型。column
jdbcTypeJDBC类型是紧紧需要对插入,更新和删除可能为空的列进行处理。
typeHandler类型处理器。使用这个属性,可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。
4.8.association

• 复杂对象映射
• POJO中的属性可能会是一个对象
• 我们可以使用联合查询,并以级联属性的方式封
装对象。


        
        
        
        
        
    

• 使用association标签定义对象的封装规则。


        
        
        
        
        
        
            
            
        
    

association-分段查询


        
        
        
        
        
        
    

select:调用目标的方法查询当前属性的值
column:将指定列的值传入目标方法

association-分段查询&延迟加载:
开启延迟加载和属性按需加载

		
		

Collection-集合类型&嵌套结果集

select id="getEmpByIdStep" resultMap="MyEmployee">
    select  * from tbl_employee where id=#{id}



        
        
        
        
        
        
    
五、MyBatis-动态SQL
  • 动态 SQL是MyBatis强大特性之一。极大的简化我们拼装
    SQL的操作。
  • 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处
    理器相似。
  • MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作。
    – if
    – choose (when, otherwise)
    – trim (where, set)
    – foreach
5.1.if
    
    
        select * from tbl_employee
        
            
                
                    id=#{id}
                
                
                    last_name like #{lastName}
                
                
                    gender=#{gender}
                
            
        
    
5.3.trim (where, set)

where

select id="getEmpIf" resultType="com.tedu.java.bean.Employee">
        select * from tbl_employee
        
            
                id=#{id} and
            
            
                last_name=#{lastName} and
            
            
                email={email} and
            
            
                gender=#{gender}
            
        
    

set


        update tbl_employee
        
            
                last_name=#{lastName},
            
            
                email=#{emial},
            
            
                gender=#{gender}
            
        
        
            id=#{id}
        
    

trim


        select * from tbl_employee where id in
        
        
            #{item_id}
        
    
六、MyBatis-缓存机制
  • MyBatis 包含一个非常强大的查询缓存特性,它可以非
    常方便地配置和定制。缓存可以极大的提升查询效率。
  • MyBatis系统中默认定义了两级缓存。
  • 一级缓存和二级缓存。
    – 1、默认情况下,只有一级缓存(SqlSession级别的缓存,
    也称为本地缓存)开启。
    – 2、二级缓存需要手动开启和配置,他是基于namespace级
    别的缓存。
    – 3、为了提高扩展性。MyBatis定义了缓存接口Cache。我们
    可以通过实现Cache接口来自定义二级缓存。
6.1.一级缓存
  • 一级缓存(local cache), 即本地缓存, 作用域默认
    为sqlSession。当 Session flush 或 close 后, 该
    Session 中的所有 Cache 将被清空。
  • 本地缓存不能被关闭, 但可以调用 clearCache()
    来清空本地缓存, 或者改变缓存的作用域。
  • 在mybatis3.1之后, 可以配置本地缓存的作用域.
    在 mybatis.xml 中配置。
localCacheScopeMybatis利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。默认值为SESSION,这种情况下会缓存一个会话中执行的所有查询。如设置STATEMENT,本地会话仅用在语句执行上,对相同SqlSession的不同调用将不会共享数据SESSION/STETEMENTSESSION

一级缓存演示&失效情况

  1. 同一次会话期间只要查询过的数据都会保存在当
    前SqlSession的一个Map中
    –key:hashCode+查询的SqlId+编写的sql查询语句+参数。
  2. 一级缓存失效的四种情况
    – 1、不同的SqlSession对应不同的一级缓存
    – 2、同一个SqlSession但是查询条件不同
    – 3、同一个SqlSession两次查询期间执行了任何一次增
    删改操作
    – 4、同一个SqlSession两次查询期间手动清空了缓存
6.2.二级缓存
  1. 二级缓存(second level cache),全局作用域缓存。
  2. 二级缓存默认不开启,需要手动配置。
  3. MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口。
  4. 二级缓存在 SqlSession 关闭或提交之后才会生效。
  5. 使用步骤:
    a.全局配置文件中开启二级缓存:。
    b.需要使用二级缓存的映射文件处使用cache配置缓存
    c.注意:POJO需要实现Serializable接口。
6.3.缓存相关属性
  1. eviction=“FIFO”:缓存回收策略:
    a.LRU – 最近最少使用的:移除最长时间不被使用的对象。
    b.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    c.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    d.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    e.默认的是 LRU。
  2. flushInterval:刷新间隔,单位毫秒。
    a.默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
  3. size:引用数目,正整数。
    a.代表缓存最多可以存储多少个对象,太大容易导致内存溢出。
  4. readOnly:只读,true/false。
    a.true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
    b.false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。
6.4.缓存有关设置
  1. 全局setting的cacheEnable:配置二级缓存的开关。一级缓存一直是打开的。
  2. select标签的useCache属性:配置这个select是否使用二级缓存。一级缓存一直是使用的。
  3. sql标签的flushCache属性:增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认flushCache=false。
  4. sqlSession.clearCache():只是用来清除一级缓存。
  5. 当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
6.5.第三方缓存整合
  1. EhCache 是一个纯Java的进程内缓存框架,具有快速、精
    干等特点,是Hibernate中默认的CacheProvider。
  2. MyBatis定义了Cache接口方便我们进行自定义扩展。
  3. 步骤:
    a.导入ehcache包,以及整合包,日志包
    ehcache-core-2.6.8.jar、mybatis-ehcache-1.0.3.jar
    slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar
    b.编写ehcache.xml配置文件


 
 
 
 
 

 

  1. 配置cache标签:



    
    
    

    

    @Test
    public void testFirstLevelCache(){
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
        Employee empById = mapper.getEmpById(2);
        System.out.println(empById);
        SqlSessionFactory sqlSessionFactory1 = getSqlSessionFactory();
        SqlSession openSession1 = sqlSessionFactory1.openSession();
        EmployeeMapper mapper1 = openSession1.getMapper(EmployeeMapper.class);
        Employee empById1 = mapper1.getEmpById(2);
        System.out.println(empById1);
        //true  没有创建新的对象
        System.out.println(empById==empById1);
        openSession.close();
    }

    @Test
    public void testSecondLevelCache(){
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        SqlSession openSession1 = sqlSessionFactory.openSession();
        EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
        EmployeeMapper mapper1 = openSession1.getMapper(EmployeeMapper.class);
        Employee empById = mapper.getEmpById(2);
        System.out.println(empById);
        openSession.close();
        //第二次查询出的数据是在二级缓存中拿到的
        Employee empById1 = mapper1.getEmpById(2);
        System.out.println(empById1);
        openSession1.close();


    }


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

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

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