Mybatis行为配置之Ⅲ—其他行为配置项说明

专栏精选

引入Mybatis

Mybatis的快速入门

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

mapper映射的参数和结果

Mybatis复杂类型的结果映射

Mybatis基于注解的结果映射

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

再谈动态SQL

Mybatis配置入门

Mybatis行为配置之Ⅰ—缓存

Mybatis行为配置之Ⅱ—结果相关配置项说明

文章目录

  • 专栏精选
  • 引言
  • 摘要
  • 正文
      • defaultExecutorType
      • defaultStatementTimeout
      • defaultResultSetType
      • safeRowBoundsEnabled
      • safeResultHandlerEnabled
      • jdbcTypeForNull
      • defaultScriptingLanguage
      • defaultEnumTypeHandler
      • callSettersOnNulls
      • useActualParamName
      • returnInstanceForEmptyRow
  • 总结

引言

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

摘要

在这篇文章中,我们将了解剩下的关于Mybatis行为的配置,在mybatis项目开发过程中这些配置可能并不常用,而且大多数情况下都是使用默认配置,了解这些配置的意义可以让我们在解决很多罕见异常问题时有的放矢,不至于手忙脚乱。那么准备好开启今天的神奇之旅了吗?

正文

首图

今天我们介绍Mybatis中最后几个控制Mybatis行为的配置项,它们是

defaultExecutorType

备注:配置默认的执行器。

默认值:SIMPLE

可选值:

说明对应的Executor实现类
SIMPLE普通的执行器,使用JDBC默认StatementSimpleExecutor
REUSE预处理语句执行器,使用JDBC的PreparedStatementReuseExecutor
BATCH重用语句+批量更新执行器BatchExecutor

建议值:SIMPLE

建议原因:SIMPLE比较通用。如果有特殊需求,可以通过 SqlSessionFactoryBuilder#openSession(ExecutorType execType)方法获取到包含对应的Executor的SqlSession。

注:Executor保存在 org.apache.ibatis.session.defaults.DefaultSqlSession类中。

批量插入数据的代码示例

 public class EnvConfigTest {    
     private SqlSessionFactory sqlSessionFactory;    
     private SqlSession sqlSession;  
       
     @Test    
     public void testBatchInsert(){    
         List<AppTestEntity> list=new ArrayList<>();    
         AppTestEntityBuilder builder = new AppTestEntityBuilder();    
         builder.setAppName("test-name").setAppCode("test-name-code").setAuthType("1").setCreator("junit");    
         list.add(builder.build());    
         //省略n个list.add    
         //关键在ExecutorType.BATCH  
         SqlSession session = this.sqlSessionFactory.openSession(ExecutorType.BATCH);    
         ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);    
         list.stream().forEach(o->{    
             mapper.addApp(o);    
         });    
         session.commit();    
         session.close();    
     }    
 }

defaultStatementTimeout

备注:等待数据库响应的秒数。这项配置需要数据库驱动的支持,在Mysql中此项配置基本无效,在postgres数据库中此配置有效
默认值:null
可选值:任意正整数
建议值:根据实际情况设置
建议原因:取决于数据库硬件和配置

Postgres配置下的测试代码:

public class PostgresTest {  
    private SqlSessionFactory sqlSessionFactory;  
    private SqlSession sqlSession;  
  
    @Before  
    public void before(){  
        try (InputStream inputStream = PostgresTest.class.getResourceAsStream("/mybatis-config.xml")){  
            this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream,"postgres9");  
  
            this.sqlSession=this.sqlSessionFactory.openSession();  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    @After  
    public void after(){  
        this.sqlSession.clearCache();  
        this.sqlSession.close();  
    }  
	//新增十万条数据
    @Test  
    public void testBatchInsert(){  
        List<AppTestEntity> list=new ArrayList<>();  
        AppTestEntityBuilder builder = new AppTestEntityBuilder();  
        builder.setAppName("test-name").setAppCode("test-name-code").setAuthType("1").setCreator("junit");  
        for (int i = 0; i < 100000; i++) {  
            AppTestEntity e = builder.build();  
            e.setId(((long) i+1));  
            list.add(e);  
        }  
        //省略n个list.add  
  
        SqlSession session = this.sqlSessionFactory.openSession(ExecutorType.BATCH);  
        ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);  
        list.stream().forEach(o->{  
            mapper.addApp(o);  
        });  
        session.commit();  
        session.close();  
    }  
	//查询测试
    @Test  
    public void testFetchSize(){  
        SimpleQueryMapper mapper = this.sqlSession.getMapper(SimpleQueryMapper.class);  
        long start = System.currentTimeMillis();  
        List<AppTestEntity> list = mapper.queryList("1");  
        long gap = System.currentTimeMillis() - start;  
        System.out.println("selected result size: "+list.size());  
        System.out.println("selected time: "+gap);  
    }  
}

配置 <setting name="defaultFetchSize" value="1"/>后的输出

selected result size: 100000
selected time: 8994

配置 <setting name="defaultFetchSize" value="1000"/>后的输出

selected result size: 100000
selected time: 413

不配置情况下的输出

selected result size: 100000
selected time: 418

细节 这里需要注意,此配置会被 fetchSize属性覆盖。fetchSize可以通过以下方式设置

  1. 注解的方式
@Select(value = "select * from app_test where auth_type=#{type}")  
@Options(fetchSize = 1000)  
List<AppTestEntity> queryList(@Param("type") String type);
  1. 标签的方式
<select id="queryList" resultType="AppTestEntity" fetchSize="1000">  
    select * from app_test where auth_type=#{type}
</select>

defaultResultSetType

备注:指定语句默认的滚动策略
可选值:

配置值说明
FORWARD_ONLY索引只能向后方滚动,不能往前
SCROLL_SENSITIVE索引可向前后滚动,且更新敏感
SCROLL_INSENSITIVE索引可向前后滚动,且更新不敏感
DEFAULT默认,效果和不设置相同

默认值:null(DEFAULT)
建议值:不设置
建议原因:不常用,此配置是对jdbc的行为控制,而在mybatis项目中不会直接操作jdbc

safeRowBoundsEnabled

备注:是否允许在嵌套语句(子查询)中使用分页API(RowBounds)。如果允许使用则设置为 false
默认值:false
建议值:
建议原因:

此配置常见的生效情况是,调用了 sqlSession#selectList(String statement,Object param,RowBounds rowBounds)这个方法,而参数statement又是嵌套语句,如以下测试代码:

@Test  
public void testSafeRow(){  
    List objects = this.sqlSession.selectList("top.sunyog.mybatis.mapper.SimpleQueryMapper.queryAppDetail", 1, new RowBounds(0, 1));  
    for (Object obj : objects) {  
        System.out.println(obj);  
    }  
}

此代码在默认配置情况下可以正常输出

AppTestEntity{id=null, appName='测试应用1', appCode='ceshi', authType='1', createDate=2023-10-31, creator='admin', appStatus='3', authTypeDict=DictTest{dictName='NONE', dictCode='1', dictType='app_auth_type', dictSort=0}, appStatusDict=DictTest{dictName='正常应用', dictCode='3', dictType='app_status', dictSort=0}, services=[ServiceTestEntity{id=3, serviceName='注册中心', serviceCode='nacos-service', servicePath='/nacos', appId=1}]}

而配置 <setting name="safeRowBoundsEnabled" value="true"/>后,会报错

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.executor.ExecutorException: Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. Use safeRowBoundsEnabled=false setting to bypass this check.
### The error may exist in mapper/SimpleQueryMapper.xml
### The error may involve top.sunyog.mybatis.mapper.SimpleQueryMapper.queryAppDetail
### The error occurred while handling results
### SQL: select t1.*             ,t2.dict_code as auth_type_dc,t2.dict_name as auth_type_dn,t2.dict_type as auth_type_dt,t2.dict_sort as auth_type_ds         from (             select id,app_name,app_code,auth_type,create_date,creator,app_status from app_test where id=?         ) t1 left join (             select dict_code,dict_name,dict_type,dict_sort from dict_test where dict_type='app_auth_type'         ) t2 on t1.auth_type=t2.dict_code
### Cause: org.apache.ibatis.executor.ExecutorException: Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. Use safeRowBoundsEnabled=false setting to bypass this check.

safeResultHandlerEnabled

备注:是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false
默认值:true
建议值:按实际情况设置
建议原因:
结果处理器ResultHandler的使用方法见Mybatis基于注解的结果映射这篇文章

jdbcTypeForNull

备注:当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER
可选值:org.apache.ibatis.type.JdbcType 常量
默认值:OTHER
建议值:不设置
建议原因:

defaultScriptingLanguage

备注:指定动态 SQL 生成使用的默认脚本语言。
默认值:org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
建议值:不设置
建议原因:不常用

defaultEnumTypeHandler

备注:指定枚举类型的默认TypeHandler,关于枚举类型的TypeHandler使用示例,见[[Mybatis基础#枚举类型映射]]
默认值:EnumTypeHandler
建议值:按实际情况设置,建议设置为 EnumOrdinalTypeHandler
建议原因:实际应用中,枚举类型大多数都是顺序编码的字典值

callSettersOnNulls

备注:指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法
默认值:false
建议值:true
建议原因:返回值中某个字段为null时,再map对象中也会插入这个对应的key,这样可以减少对map的 containsKey方法操作。

通过以下代码测试设置的行为

@Test  
public void testNullSet(){  
    SimpleQueryMapper mapper = this.sqlSession.getMapper(SimpleQueryMapper.class);  
    //在这之前先执行这个sql
    //update app_test set creator=null where id=13;
    List<Map<String, Object>> list = mapper.queryMapRes(13);  
    System.out.println(list);  
}

默认设置时的输出:

[{app_name=test-name, auth_type=1, id=13, create_date=2023-11-30, app_code=test-name-code}]

配置 <setting name="callSettersOnNulls" value="true"/>时的输出

[{app_name=test-name, auth_type=1, creator=null, id=13, create_date=2023-11-30, app_code=test-name-code}]

useActualParamName

备注:允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,项目必须采用 Java 8 编译,并且加上 -parameters 选项
默认值:true
建议值:true
建议原因:

parameters选项的添加方式为修改maven的pom.xml文件

细节:这个插件安装或修改后,需要执行maven:cleanmaven:compile后才能生效

<project>
...
    <build>  
        <plugins>            
	        <plugin>                
		        <groupId>org.apache.maven.plugins</groupId>  
	            <artifactId>maven-compiler-plugin</artifactId>  
	            <configuration>                  
	                <compilerArgs>                        
		                <arg>-parameters</arg>  
	                </compilerArgs>                
	            </configuration>            
	        </plugin>        
        </plugins>    
    </build>
</project>

新增测试代码

@Test  
public void testMethodParam(){  
    SimpleQueryMapper mapper = this.sqlSession.getMapper(SimpleQueryMapper.class);  
    List<AppTestEntity> list = mapper.getAppByStatusAndAuthType("3","1");  
    System.out.println(list);  
}
public interface SimpleQueryMapper {
	//注意,这里的入参没有添加@Param注解
    List<AppTestEntity> getAppByStatusAndAuthType(String status,String authType);  
}
<select id="getAppByStatusAndAuthType" resultType="appTestEntity">  
    <include refid="top.sunyog.mybatis.mapper.ApplicationRepository.query_column"></include>  
    where app_status=#{status} and auth_type=#{authType}  
</select>

配置 <setting name="useActualParamName" value="false"/>后执行报错

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'status' not found. Available parameters are [0, 1, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'status' not found. Available parameters are [0, 1, param1, param2]

默认配置或 <setting name="useActualParamName" value="true"/>配置下,打印结果

[AppTestEntity{id=1, appName='测试应用1', appCode='ceshi', authType='1', createDate=2023-10-31, creator='admin', appStatus='3', authTypeDict=null, appStatusDict=null, services=null}]

returnInstanceForEmptyRow

备注:当返回行的所有列都是空时,默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集
默认值:false
建议值:true
建议原因:可减少空指针验证

测试代码

public interface SimpleQueryMapper {
    @Select("select name,code from empty_table_test where 1=1 limit 0,1")  
    Map<String, Object> queryEmptyMap(int i);  
}

public class EnvConfigTest {
	@Test  
	public void testReturnEmptyObj(){  
	    SimpleQueryMapper mapper = this.sqlSession.getMapper(SimpleQueryMapper.class);  
	    Map<String,Object> entity = mapper.queryEmptyMap(112);  
	    System.out.println(entity);  
	}
}

新增可为空的测试表

create table empty_table_test  
(  
    name int         null,  
    code varchar(32) null  
);
insert into empty_table_test(name,code) values(null,null),(null,null)

默认配置下的输出

null

配置 <setting name="returnInstanceForEmptyRow" value="true"/>时的输出

{}

总结

今天介绍的配置项在日常工作中很多都不是很常用,但了解这些配置可以减少很多不必要的错误,甚至解决一些罕见的异常问题。如 returnInstanceForEmptyRow这个配置能在很大程度上减少空指针异常的出现。


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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/277599.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构和算法】---二叉树(2)--堆的实现和应用

目录 一、堆的概念及结构二、堆结构的实现2.1堆向下调整算法2.2堆向上调整算法2.3删除堆顶元素2.4插入元素2.5其他函数接口 三、堆结构的应用3.1堆排序3.2Top-k问题 四、堆概念及结构相关题目 一、堆的概念及结构 如果有一个数字集合&#xff0c;并把它的所有元素按完全二叉树…

水库大坝安全监测设计与施工经验

随着我国的科技水平不断上升&#xff0c;带动了我国的水电建设向更高层次发展。目前&#xff0c;我国的水电站大坝已有上百座&#xff0c;并且大坝安全检测仪器质量与先进技术不断更新发展&#xff0c;如今水电站大坝数据信息采集与观测资料分析&#xff0c;能够有效提高水库大…

C语言编程入门 – 编写第一个Hello, world程序

C语言编程入门 – 编写第一个Hello, world程序 C Programming Entry - Write the first application called “Hello, world!” By JacksonML C语言编程很容易&#xff01; 本文开始&#xff0c;将带领你走过C语言编程之旅&#xff0c;通过实例使你对她颇感兴趣&#xff0c;一…

openGauss学习笔记-176 openGauss 数据库运维-实例主备切换

文章目录 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换176.1 操作场景176.2 操作步骤176.3 示例176.4 错误排查176.5 异常处理 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换 176.1 操作场景 openGauss在运行过程中&#xff0c;数据库管理员可能需要…

mongodb聚合_删除_可视化工具

3.5 MongoDB中limit和skip MongoDB Limit() 方法 如果你需要在MongoDB中读取指定数量的数据记录&#xff0c;可以使用MongoDB的Limit方法&#xff0c;limit()方法接受一个数字参数&#xff0c;该参数指定从MongoDB中读取的记录条数。limit()方法基本语法如下所示&#xff1a;…

听GPT 讲Rust源代码--src/tools(31)

File: rust/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs rust/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs这个文件是Clippy的一个Lint规则&#xff0c;用于检查在模式匹配中是否存在冗余的守卫条件&#xff08;guard&#xff09;。 在…

英语中修饰头发的形容词顺序是怎么样的(加补充)

一、英语描述发型 :漂亮长短形状颜色头发。 例如她有一头美丽的黑色的直发。She has beautiful long straight black hair.二、多个形容词修饰同一名词时的顺序是固定的&#xff0c;其顺序为&#xff1a;①冠词、指示代词、不定代词、物主代词②序数词基数词③一般性描绘形容词…

蓝牙简学(一)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、蓝牙广播二、通过设备广播数据三、蓝牙广播类型四、蓝牙状态切换 一、蓝牙广播 1、低功耗蓝牙一共有40个信道&#xff0c;频段范围从2402MHz到2480Mhz&#xf…

idea的pom.xml文件灰色删除线解决办法

以上是点击了移除module后就变成这样 如果再次对着已移除的module右键会发现有个delete&#xff0c;点击这个是真删了&#xff0c;要谨慎备份哦 解决方案&#xff1a;恢复误操作remove module的解决方法 idea最右边&#xff0c;有个Maven控件&#xff0c;找到要恢复的module&a…

连理:保险中的实名DID创新应用

2023年12月12日&#xff0c;BSN实名DID服务发布会在北京成功举办&#xff0c;会上正式发布了BSN实名DID服务。这一服务充分融合了BSN区块链服务网络和CTID数字身份链两大基础设施&#xff0c;满足“前台匿名、后台实名”的管理要求&#xff0c;对服务数字经济发展、支撑国家数据…

TiDB 7.1 多租户在中泰证券中的应用

本文详细介绍了中泰证券在系统国产化改造项目中采用 TiDB 多租户技术的实施过程。文章分析了中泰证券数据库系统现状以及引入 TiDB 资源管控技术的必要性&#xff0c;探讨了 TiDB 多租户的关键特性&#xff0c;并阐述了在实际应用中的具体操作步骤。通过该技术的应用&#xff0…

bat命令清理Window应用注册表(Unity开发Window应用)

bat命令清理Window应用注册表&#xff08;Unity开发Window应用&#xff09; 介绍出现的问题方案一方案二方案二解决方案1. 首先使用【Win】【R】组合快捷键&#xff0c;快速打开运行命令框&#xff0c;在打开后面键入命令&#xff1a;【Regedit】2. 完后后按回车键&#xff08;…

华为发布的工业软件三大难题: 面向装配场景,10万+零件的超大规模几何约束系统的求解问题

华为发布的工业软件三大难题: 面向装配场景&#xff0c;10万零件的超大规模几何约束系统的求解问题。 一方面是算法改进&#xff0c; 另一方面是对云几何内核的需求&#xff1a;并行计算、分布式、缓存、集群等云计算技术对CAD系统的辅助提升。 云几何内核可以(/需要能)支撑…

HTML+CSS+JS网页设计期末课程大作业 web课程设计 web前端开发 网页规划与设计

HTMLCSSJS网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计 &#x1f4a5; 文章目录一、&#x1f6a9; 网站描述二、&#x1f38c; 网站介绍三、&#x1f3f4; 网站类型A 个人博客主题B 人物明星主题C 旅游主题D 游戏主题E 动漫主题F 美食主题G 校园主题H 企…

GPT编程(1)八分类图像数据集转换为二分类

一个核心问题就是要将这八类数据图片全部重命名&#xff0c;尝试了一步到位 有一个图像数据集&#xff0c;有八个类别amusement,anger,awe,contentment,disgust, excitement, fear,sadness的图片&#xff0c;每张图片被命名为“类别数字”。采用遍历的方式&#xff0c;按顺序阅…

每天坐在电脑前10小时的投资者的现货黄金投资秘密

很多人在现货黄金市场中苦作舟&#xff0c;希望通过交易、实践来找出市场中的奥秘。笔者最近看了一个每天坐在电脑面前十个小时以上做分析和投资的投资者的经验介绍&#xff0c;他道出了一些投资的秘密&#xff0c;笔者认为&#xff0c;这是适合现货黄金投资者借鉴和学习的&…

7.7复原IP地址(LC93-M)

算法&#xff1a; 根据题意 有效的 IP 地址 &#xff1a; &#xff08;1&#xff09;由四个整数构成 &#xff08;2&#xff09;每个整数位于 0 到 255 之间 &#xff08;3&#xff09;每个整数不能含有前导 0&#xff0c;如011、021等&#xff0c;但是可以有单独的一个“…

【笔记】Spring的事务是如何回滚的/Spring的事务管理是如何实现的

Spring的事务是如何回滚的/Spring的事务管理是如何实现的 数据库&#xff08;Spring事务&#xff09; 1、建立连接、开启事务&#xff08;准备工作&#xff09; 2、进行sql操作&#xff08;业务逻辑&#xff09; 3、执行成功&#xff0c;则commit&#xff1b; 执行失败&#x…

MySQL 执行过程

MySQL 的执行流程也确实是一个复杂的过程&#xff0c;它涉及多个组件的协同工作&#xff0c;故而在面试或者工作的过程中很容易陷入迷惑和误区。 MySQL 执行过程 本篇将以 MySQL 常见的 InnoDB 存储引擎为例&#xff0c;为大家详细介绍 SQL 语句的执行流程。从连接器开始&…

直播的营销多样性

直播的营销多样性主要体现在以下几个方面: 1.互动性高:直播能够实时互动&#xff0c;观众可以提问、评论、点赞,甚至直接在直播中购买商品&#xff0c;这种互动性使得直播成为一种非常有效的营销手段。 2.内容生动:直播能够以视频的形式展示产品或服务&#xff0c;相比传统的…