Mybatis配置入门

2023-12-29 06:07:25

专栏精选

引入Mybatis

Mybatis的快速入门

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

mapper映射的参数和结果

Mybatis复杂类型的结果映射

Mybatis基于注解的结果映射

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

再谈动态SQL

摘要

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

引言

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

正文

首图

配置

配置读取

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

xml文件配置

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

<?xml version="1.0" encoding="UTF-8" ?>  
<!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>  

	<!--设置mapper映射文件/映射接口的位置-->
    <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类属性类型功能备注
属性配置<properties>variablesProperties自定义的k-v属性
环境配置<environment>environmentEnvironment环境配置,如数据源
行为配置<settings>各配置项不同一般是boolean,有例外用于配置mybatis的行为
类型别名<typeAliases>typeAliasRegistryTypeAliasRegistry配置类型别名
类型处理器<typeHandlers>typeHandlerRegistryTypeHandlerRegistry配置类型转换器
映射配置<mappers>mapperRegistryMapperRegistry配置mapper映射类/映射文件的位置
插件配置<plugins>interceptorChainInterceptorChain配置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>
	<!--引用当前目录下的mysql-env.properties文件-->
	<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实例只能有一个环境是可用的,通过<environments default="">属性控制。

<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 上下文的数据源引用。

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

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

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

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

类型别名

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

<configuration>
	<typeAliases>  
	    <package name="top.sunyog.common.entity"/>
	</typeAliases>
</configuration>
<!--xml映射文件-->
<select id="queryById" resultType="AppTestEntity">  
    <include refid="query_column"/> where id=#{id} limit 0,1  
</select>

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

<!--app代表这个类-->
<typeAlias type="top.sunyog.common.entity.AppTestEntity" alias="app"/>
<!--使用类名称(非全名)代表这个类,如
appTestEntity或AppTestEntity代表top.sunyog.common.entity.AppTestEntity
-->
<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<T>接口或继承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. 映射器

📩 联系方式
邮箱:qijilaoli@foxmail.com

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

文章来源:https://blog.csdn.net/qq_43408971/article/details/135279360
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。