Mybatis配置入门

专栏精选

引入Mybatis

Mybatis的快速入门

Mybatis的增删改查扩展功能说明

mapper映射的参数和结果

Mybatis复杂类型的结果映射

Mybatis基于注解的结果映射

Mybatis枚举类型处理和类型处理器

再谈动态SQL

文章目录

  • 专栏精选
  • 摘要
  • 引言
  • 正文
    • 配置读取
      • xml文件配置
      • javaAPI配置
    • 属性配置
    • 环境配置
      • 事务管理器
        • 内置事务管理器
        • 自定义事务管理器
      • 数据源
    • 类型别名
    • 类型处理器
    • 映射器配置
  • 总结

摘要

在这篇文章中,我们将进入Mybatis配置的世界,了解Mybatis的基本配置方法,包括读取配置的方式、属性配置、环境配置、类型别名配置、类型处理器配置、映射器配置。准备好开启今天的神奇之旅了吗?

引言

大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。欢迎来到我的频道,这里汇聚了汇集编程技巧、代码示例和技术教程,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 ,期待在这里与你共同度过美好的时光️。今天要和大家分享的内容是Mybatis配置说明。做好准备,Let’s go

正文

首图

配置

配置读取

mybatis项目读取配置的方式有两种,一种是通过读取xml配置文件的方式读取,另一种是通过java代码进行配置,这两中方式都是通过SqlSessionFactory这个类完成对mybatis的配置工作,这两种方式的样例代码如下:

xml文件配置

xml配置文件示例(以下只是常用配置)

  
DOCTYPE configuration  
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
        "https://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
	
    <properties resource="mysql-env.properties"/>  
    
    <settings>  
	    
        <setting name="mapUnderscoreToCamelCase" value="true"/>  
    settings>  
    
    <typeAliases>  
	    
        <package name="top.sunyog.common.entity"/>  
    typeAliases>  
    
    <typeHandlers>    
            
	    <typeHandler handler="top.sunyog.mybatis.handler.LocalDateHandler"/>  
    typeHandlers>    
    
    <environments default="mysql">  
    
        <environment id="mysql">  
            <transactionManager type="JDBC">transactionManager>  
            <dataSource type="POOLED">  
	            
                <property name="driver" value="${driver}"/>  
                <property name="url" value="${url}"/>  
                <property name="username" value="${username}"/>  
                <property name="password" value="${password}"/>  
            dataSource>        
        environment>    
    environments>  

	
    <mappers>        
	    <mapper resource="mapper/ApplicationMapper.xml"/>  
    mappers>  
configuration>

读取xml配置

public class MybatisApp{
	private static SqlSessionFactory sqlSessionFactory;
	
	public static void startConfigFromXml(){
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
		
		try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml");  
		        InputStreamReader reader=new InputStreamReader(in)) {  
		    this.sqlSessionFactory = builder.build(reader);  
		} catch (IOException e) {  
		    System.out.println("文件路径读取错误");  
		}
	}
}

javaAPI配置

public class MybatisApp{
    private static SqlSessionFactory sqlSessionFactory;
	private static void startConfigFromApi(){
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setPassword("123456admin");
        dataSource.setUrl("jdbc:mysql://db.sunyog.top:13306/sunyog_db");
        dataSource.setUser("root");
        JdbcTransactionFactory transFactory = new JdbcTransactionFactory();
        Environment env = new Environment("env-2", transFactory,dataSource);

        Configuration config = new Configuration();
        config.setEnvironment(env);
        config.getMapperRegistry().addMappers("top.sunyog.my.mapper");
        config.getTypeAliasRegistry().registerAliases("top.sunyog.my.entity");
        config.setMapUnderscoreToCamelCase(true);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    }	
}

通过以上示例,并分析Mybatis代码可以看出,Mybatis通过org.apache.ibatis.session.Configuration类来保存所有的配置,通过org.apache.ibatis.session.SqlSessionFactoryBuilder类来 读取/构建 配置。xml和API的区别在于,API的方式直接通过Configuration类创建DefaultSqlSessionFactory类,而XML的方式是先读取XML文件构建Configuration(这项工作在org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration方法中),再创建DefaultSqlSessionFactory

xml配置文件标签和Configuration类属性的对应关系

名称 标签 Configuration类属性名 Configuration类属性类型 功能备注
属性配置 variables Properties 自定义的k-v属性
环境配置 environment Environment 环境配置,如数据源
行为配置 各配置项不同 一般是boolean,有例外 用于配置mybatis的行为
类型别名 typeAliasRegistry TypeAliasRegistry 配置类型别名
类型处理器 typeHandlerRegistry TypeHandlerRegistry 配置类型转换器
映射配置 mapperRegistry MapperRegistry 配置mapper映射类/映射文件的位置
插件配置 interceptorChain InterceptorChain 配置mybatis插件

属性配置

属性配置可以设置程序或后续配置中将要用到的k-v型参数。属性配置的方式有四种:

  1. property元素标签配置(可以与后两种的其中一种混合使用)
  2. 外部资源配置
  3. 远程资源配置(注意,外部配置和远程配置只能存在一个)
  4. ConfigurationAPI配置
  5. 从Mybatisv3.4.2开始,可以通过${uName:zhangsan}的方式为没有指定的属性名设置默认值

properties元素配置:

<configuration>
	<properties>  
	    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>  
	    <property name="url" value="jdbc:mysql://db.sunyog.top:13306/sunyog_db"/>  
	    <property name="username" value="root"/>  
	    <property name="password" value="123456admin"/>  
	    <property name="test-key" value="test-value-c"/>  
	properties>
configuration>

外部资源配置:

driver=com.mysql.cj.jdbc.Driver  
url=jdbc:mysql://db.sunyog.top:13306/sunyog_db  
username=root  
password=123456admin  
test-key=test-value-b
<configuration>
	
	<properties resource="mysql-env.properties"/>
configuration>

远程资源的配置方式为:

test-key=test-value-a
<configuration>
	<properties url="http://img.sunyog.top/config/mybatis-blog.properties"/>
configuration>

混合写法:

<properties resource="mysql-env.properties">  
    <property name="test-key" value="test-value-c"/>  
properties>

如果混合使用两种方式,遇到同名配置时,Mybatis的处理优先级为:

C o n f i g u r a t i o n A P I > r e s o u r c e 或 u r l > p r o p e r t y 元素 Configuration API > resource或url > property元素 ConfigurationAPI>resourceurl>property元素

以上的属性配置可以在mybatis的配置文件中通过 ${}符号引用,亦可以在mybatis程序中通过Configuration类使用,MybatisAPI引用示例:

public class MybatisConfigService extends MybatisService{  
    @Override  
    public void doService() {  
        SqlSessionFactory sqlSessionFactory = MybatisAppContext.getSqlSessionFactory();  
        Object v = sqlSessionFactory.getConfiguration().getVariables().get("test-key");  
        System.out.println(v);  
    }  
}

//mybatis容器
public class MybatisAppContext {  
    private static SqlSessionFactory sqlSessionFactory = null;
    
	static {  
	    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
	    try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml");  
	            InputStreamReader reader=new InputStreamReader(in)) {  
	        sqlSessionFactory = builder.build(reader);  
	    } catch (IOException e) {  
	        System.out.println("文件路径读取错误");  
	    } 
    } 
    
    public static SqlSessionFactory getSqlSessionFactory(){  
        return sqlSessionFactory;  
    }  
}

//打印结果如下
test-value-b

环境配置

环境配置主要用于配置数据源和事务处理器,Mybatis同时可以配置多个环境,但同一个SqlSessionFactory实例只能有一个环境是可用的,通过属性控制。

<configuration>
	<environments default="mysql">  
	    <environment id="mysql">  
	        <transactionManager type="JDBC">transactionManager>  
	        <dataSource type="POOLED">  
	            <property name="driver" value="${driver}"/>  
	            <property name="url" value="${url}"/>  
	            <property name="username" value="${username}"/>  
	            <property name="password" value="${password}"/>  
	        dataSource>    
        environment>
        <environment id="mysql8">  
		    <transactionManager type="MANAGED">transactionManager>  
		    <dataSource type="UNPOOLED">  
		        <property name="driver" value="${driver}"/>  
		        <property name="url" value="${url}"/>  
		        <property name="username" value="${username}"/>  
		        <property name="password" value="${password}"/>  
		    dataSource>
	    environment>
    environments>
configuration>

测试多数据源应用

public class EnvConfigTest {  
    @Test  
    public void test2Env() throws IOException {  
        InputStream input = null;  
        InputStream input2=null;  
        try {  
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
            input = EnvConfigTest.class.getResourceAsStream("/mybatis-config.xml");  
            SqlSessionFactory factory_1 = builder.build(input);  
            input2=EnvConfigTest.class.getResourceAsStream("/mybatis-config.xml");  
            SqlSessionFactory factory_2 = builder.build(input2, "mysql8");  
  
            TransactionFactory transaction_1 = factory_1.getConfiguration().getEnvironment().getTransactionFactory();  
            TransactionFactory transaction_2 = factory_2.getConfiguration().getEnvironment().getTransactionFactory();  
  
            System.out.println(transaction_1.getClass());  
            System.out.println(transaction_2.getClass());  
        } finally {  
            if (input !=null){  
                input.close();  
            }  
            if (input2!=null){  
                input2.close();  
            }  
        }  
    }  
}

打印结果

class org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
class org.apache.ibatis.transaction.managed.ManagedTransactionFactory

事务管理器

内置事务管理器

在 MyBatis 中有两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚功能,它依赖从数据源获得的连接来管理事务作用域。默认情况下,为了与某些驱动程序兼容,它在关闭连接时启用自动提交。然而,对于某些驱动程序来说,启用自动提交不仅是不必要的,而且是一个代价高昂的操作。因此,从 3.5.10 版本开始,你可以通过将 “skipSetAutoCommitOnClose” 属性设置为 “true” 来跳过这个步骤。
  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
<transactionManager type="JDBC">
	<property name="skipSetAutoCommitOnClose" value="true"/>
transactionManager>

<transactionManager type="MANAGED">
	<property name="closeConnection" value="false"/>
transactionManager>
自定义事务管理器

除了以上两种内置的事务管理器之外,Mybatis还支持自定义事务管理器,需要实现 TransactionFactoryTransaction两个接口。使用方式如下:

  1. 实现 TransactionTransactionFactory接口
package top.sunyog.mybatis.trans;  
  
import org.apache.ibatis.transaction.Transaction;  
  
import java.sql.Connection;  
import java.sql.SQLException;  
  
/**  
 * @author Myste  
 * @since 2023/11/20 13:36  
 */public class MyTransaction implements Transaction {  
    private Connection conn;  
  
    public MyTransaction(Connection conn) {  
        this.conn=conn;  
    }  
  
    @Override  
    public Connection getConnection() throws SQLException {  
	    //设置不自动提交
	    conn.setAutoCommit(false);
        return this.conn;  
    }  
  
    @Override  
    public void commit() throws SQLException {  
	    //提交之前打印信息
	    System.out.println("自定义commit");
        this.conn.commit();  
    }  
  
    @Override  
    public void rollback() throws SQLException {  
        this.conn.rollback();  
    }  
  
    @Override  
    public void close() throws SQLException {  
        this.conn.close();  
    }  
  
    @Override  
    public Integer getTimeout() throws SQLException {  
        return null;  
    }  
}
package top.sunyog.mybatis.trans;  
  
import org.apache.ibatis.session.TransactionIsolationLevel;  
import org.apache.ibatis.transaction.Transaction;  
import org.apache.ibatis.transaction.TransactionFactory;  
  
import javax.sql.DataSource;  
import java.sql.Connection;  
import java.sql.SQLException;  
  
public class MyTransactionFactory implements TransactionFactory {  
    @Override  
    public Transaction newTransaction(Connection conn) {  
        return new MyTransaction(conn);  
    }  
  
    @Override  
    public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {  
        Transaction trans = null;  
        try {  
            Connection conn = dataSource.getConnection();  
            trans = new MyTransaction(conn);  
            return trans;  
        } catch (SQLException e) {  
            e.printStackTrace();  
            System.out.println("数据异常");  
            return null;        }  
    }  
}
  1. 配置自定义的事务处理器
<environments default="mysql">  
    <environment id="mysql">  
        <transactionManager type="top.sunyog.mybatis.trans.MyTransactionFactory">transactionManager>  
        <dataSource type="POOLED">  
            <property name="driver" value="${driver}"/>  
            <property name="url" value="${url}"/>  
            <property name="username" value="${username}"/>  
            <property name="password" value="${password}"/>  
        dataSource>    
    environment>
environments>
  1. 测试update方法
private void testUpdateStatusScript(ApplicationRepository mapper){  
    AppTestEntity param = new AppTestEntity();  
    param.setId(1L);  
    param.setAppStatus("3");  
    int row = mapper.updateByScript(param);  
    System.out.println(row);  
}

打印结果为:

1
自定义commit

查看数据库,确认状态已修改

数据源

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
有三种内建的数据源类型(也就是 type=“[UNPOOLED|POOLED|JNDI]”):

  • UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。
  • POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
  • JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

以上三种数据源的可配置项如下

配置项 数据源 备注
driver POOL和UNPOOL 驱动类全名
url POOL和UNPOOL JDBC的url地址
username POOL和UNPOOL 数据库用户名
password POOL和UNPOOL 数据库密码
defaultTransactionIsolationLevel POOL和UNPOOL 数据库事务隔离级别
defaultNetworkTimeout POOL和UNPOOL 数据库操作超时时间
poolMaximumActiveConnections POOL 连接池中活动链接数量,默认10
poolMaximumIdleConnections POOL 空闲连接数量
poolMaximumCheckoutTime POOL 在被强制返回之前,池中连接被检出的时间,默认20秒
poolTimeToWait POOL 如果获取连接花费时间超过这个数(默认20秒),连接池会打印状态日志并重新尝试获取一个连接
poolMaximumLocalBadConnectionTolerance POOL 如果一个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和
poolPingQuery POOL 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”
poolPingEnabled POOL 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false
poolPingConnectionsNotUsedFor POOL 配置 poolPingQuery 的频率。(默认值为0,仅当 poolPingEnabled 为 true 时适用)

关于数据源的配置,前四项是必填项,其他配置都有默认值。实际应用中,可根据服务器硬件配置修改个别配置。

除去以上三种数据源之外,还可以使用第三方数据源,如:c3p0druid两种数据源比较常见,其中druid为alibaba提供,国内常用。

类型别名

通过配置类型别名,可以在xml映射文件中使用别名来简化resultTypeparameterType属性,如

<configuration>
	<typeAliases>  
	    <package name="top.sunyog.common.entity"/>
	typeAliases>
configuration>

<select id="queryById" resultType="AppTestEntity">  
    <include refid="query_column"/> where id=#{id} limit 0,1  
select>

注意:可以为整个包内的所有类型设置别名,也可以为一个类设置单独的别名。两种方式的写法如下


<typeAlias type="top.sunyog.common.entity.AppTestEntity" alias="app"/>

<package name="top.sunyog.common.entity"/>

另外,mybatis内置了一部分常见的类型别名,可以在 org.apache.ibatis.type.TypeAliasRegistry这个类的构造方法中查看

public class TypeAliasRegistry {  
  ...
  public TypeAliasRegistry() {  
    registerAlias("string", String.class);  
  
    registerAlias("byte", Byte.class);  
    registerAlias("char", Character.class);  
    registerAlias("character", Character.class);  
    registerAlias("long", Long.class);  
    registerAlias("short", Short.class);  
    registerAlias("int", Integer.class);  
    registerAlias("integer", Integer.class);  
    registerAlias("double", Double.class);  
    registerAlias("float", Float.class);  
    registerAlias("boolean", Boolean.class);  
  
    registerAlias("byte[]", Byte[].class);  
    registerAlias("char[]", Character[].class);  
    registerAlias("character[]", Character[].class);  
    registerAlias("long[]", Long[].class);  
    registerAlias("short[]", Short[].class);  
    registerAlias("int[]", Integer[].class);  
    registerAlias("integer[]", Integer[].class);  
    registerAlias("double[]", Double[].class);  
    registerAlias("float[]", Float[].class);  
    registerAlias("boolean[]", Boolean[].class);  
  
    registerAlias("_byte", byte.class);  
    registerAlias("_char", char.class);  
    registerAlias("_character", char.class);  
    registerAlias("_long", long.class);  
    registerAlias("_short", short.class);  
    registerAlias("_int", int.class);  
    registerAlias("_integer", int.class);  
    registerAlias("_double", double.class);  
    registerAlias("_float", float.class);  
    registerAlias("_boolean", boolean.class);  
  
    registerAlias("_byte[]", byte[].class);  
    registerAlias("_char[]", char[].class);  
    registerAlias("_character[]", char[].class);  
    registerAlias("_long[]", long[].class);  
    registerAlias("_short[]", short[].class);  
    registerAlias("_int[]", int[].class);  
    registerAlias("_integer[]", int[].class);  
    registerAlias("_double[]", double[].class);  
    registerAlias("_float[]", float[].class);  
    registerAlias("_boolean[]", boolean[].class);  
  
    registerAlias("date", Date.class);  
    registerAlias("decimal", BigDecimal.class);  
    registerAlias("bigdecimal", BigDecimal.class);  
    registerAlias("biginteger", BigInteger.class);  
    registerAlias("object", Object.class);  
  
    registerAlias("date[]", Date[].class);  
    registerAlias("decimal[]", BigDecimal[].class);  
    registerAlias("bigdecimal[]", BigDecimal[].class);  
    registerAlias("biginteger[]", BigInteger[].class);  
    registerAlias("object[]", Object[].class);  
  
    registerAlias("map", Map.class);  
    registerAlias("hashmap", HashMap.class);  
    registerAlias("list", List.class);  
    registerAlias("arraylist", ArrayList.class);  
    registerAlias("collection", Collection.class);  
    registerAlias("iterator", Iterator.class);  
  
    registerAlias("ResultSet", ResultSet.class);  
  }
}

类型处理器

在获取到数据库查询结果时,mybatis会通过类型处理器将查询结果转换为对应的java类型,mybatis中内置了很多类型处理器,除此之外,如果内置的类型处理器不满足业务需要,还可以通过实现org.apache.ibatis.type.TypeHandler接口或继承org.apache.ibatis.type.BaseTypeHandler类的方式自定义类型处理器。

mybatis内置的类型处理器可以通过这个链接查看 https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

自定义类型处理器详见枚举类型处理和类型处理器一文

映射器配置

mybatis中的映射器包括mapper接口和mapper文件两种,mybatis程序在启动时需要读取映射器到内存中备用,所以需要指定mapper接口或mapper文件的位置。有以下几种形式

  1. 指定映射器文件的位置
<mappers>
  <mapper resource="mapper/ApplicationMapper.xml"/>
mappers>
  1. 指定mapper接口类全名
<mapper class="top.sunyog.mybatis.mapper.AppAnnoMapper"/>
  1. 将包内的接口全部注册为映射器
<package name="top.sunyog.mybatis.mapper"/>
  1. 指定外部mapper资源
<mapper url="file:///app/app_demo/mappers/ApplicationMapper.xml"/>

这里需要注意:如果通过指定mapper接口来配置映射器,需要保证接口的包路径名称和xml文件的文件夹路径名称一致,否则会因为两者对应不上而报错,除非没有xml映射文件(通过注解或代码的形式指定sql语句)。

总结

Mybatis中提供了丰富的配置项,需要我们在日常开发过程中慢慢感受配置对Mybatis行为的影响。本文我们主要学习了关于Mybatis配置的入门知识,包括配置的两种方式(XML和API)、两种配置方式之间的对应关系以及几类简单的配置,它们是

  1. 属性配置
  2. 环境配置(主要是数据源)
  3. 类型别名
  4. 类型处理器
  5. 映射器

联系方式
邮箱:[email protected]

❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页

你可能感兴趣的:(Mybatis,mybatis,java)