那些你必须知道的MyBatis实用知识点

如何定义好AI:从能力、体验到信任的评估框架 人工智能技术的落地浪潮中,企业和开发者常常陷入一个困境:模型分数持续攀升,但真实场景中的表现却难以衡量。究其根源,我们缺少对“好AI”的清晰定义。本文从机器学习评测的基本原理出发,探讨模型评估中的常见误区——公开榜单的高分不一定代表业务匹配度,准确率提升也可能牺牲用户体验。更重要的是,一个真正优秀的AI系统需要兼顾能力、体验、信任三个维度,在鲁棒性、延迟成本、错误处理、可解释性等层面达到动态平衡。文章结合工程实践,提出了一套分层指标体系与离线在线闭环的评估方法,帮助团队将模糊的“好用”转化为可度量、可执行的 阅读详情

#一、MyBatis简介
MyBatis的前身是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。2013年11月迁移到GitHub,因此目前MyBatis是由GitHub维护的。

​ 同样作为持久层框架的Hibernate在前些年非常的火,它在配置了映射文件和数据库连接文件后就可以通过Session操作,它甚至提供了HQL去操作POJO进而操作数据库的数据,几乎可以使编程人员脱离sql语言。可是为什么MyBatis却越来越受欢迎呢?我们稍稍总结如下:

Hibernate:

  • 1.不方便的全表映射,比如更新时需要发送所有的字段;

  • ​ 2.无法根据不同的条件组装不同sql;

  • ​ 3.对多表关联和复制sql查询支持较差;

  • 4.有HQL但性能较差,做不到sql优化;

  • 5.不能有效支持存储过程;

在当今的大型互联网中,灵活、sql优化,减少数据的传递是最基本的优化方法,但是Hibernate却无法满足我们的需求,而MyBatis提供了更灵活、更方便的方法。在MyBatis里,我们需要自己编写sql,虽然比Hibernate配置要多,但是是MyBatis可以配置动态sql,也可以优化sql,且支持存储过程,MyBatis几乎能做到 JDBC 所能做到的所有事情!凭借其高度灵活、可优化、易维护等特点,成为目前大型移动互联网项目的首选框架。

二:开发环境、流程及生命周期

1.开发环境

1.1 导入依赖jar包
  • 导入mybatis的jar包,如果采用Maven进行部署,只需导入mybatis坐标。

  • 导入数据库驱动jar包或坐标。

  • 代码调试阶段可导入日志工具jar包或坐标,如log4j。

  • 导入Junit单元测试坐标。

1.2 创建mybatis的主配置文件

​ 在resources目录下建立一个名字为mybatis-config.xml(名称随意)配置文件,编写所需配置信息。

1.3 准备实体类和表结构

​ 遵循开发规范:

  • 类属性命名尽量和表字段保持一致。

  • 实体类实现序列化接口。

  • 实体类属性使用包装类型定义,如Integer。

Tips: 有时可以考虑通过定义时初始化来避免可能的空指针异常!

如:private List list = new ArrayList<>() ;

1.4 创建Mapper接口(Dao接口)建立接口方法和sql映射文件

创建Mapper接口,在内定义CRUD方法。

​ Tips: 方法名唯一,需要在对应的mapper.xml文件中配置id。

在resources下创建sql映射文件。

​ Tips: 同对应的Mapper接口保持包结构及命名一致。

​ 如:Mapper接口: cn.dintalk.dao.UserMapper

​ 对应配置文件:cn.dintalk.dao.UserMapper.xml

1.5 将映射文件加入到mybatis主配置文件中

将映射文件通过引入的方式加入到mybatis的主配置文件中。

​ Tips: 所有映射文件会随主配置文件在程序运行时加入内存,任一映射文件出 错都会导致整个环境报错!(初学者经常搞混resultType和resultMap)。

1.6 编写代码进行CRUD操作

在映射文件中编写sql进行crud操作,在单元测试中,或service层中调用方法!

2.开发流程

环境搭建好后开发基本流程为:

  • 接口定义方法 。

  • Mapper.xml文件中编写sql。

  • 单元测试或service调用。

Tips: 接口中方法名称和Mapper.xml文件中sql语句的id保持一致!

3.生命周期

MyBatis的核心组件:

  • SqlSessionFactoryBuilder(构造器):根据配置信息或代码生成SqlSessionFactory

  • SqlSessionFactory(工厂接口):依靠工厂来生成SqlSession(会话)。

  • SqlSession(会话): 既可以发生sql去执行并返回结果,也可以获取Mapper的接口

  • SQL Mapper:它是MyBatis新设计的组件,它是由一个java接口和xml文件(或注解)构成的,需要给出对应的sql和映射规则。它负责发送sql去执行,并返回结果。

    ​ 正确理解并掌握上述核心组件的生命周期可以让我们写出高效的程序,还可避免带来严重的并发问题。

3.1 SqlSessionFactoryBuilder

​ 其作用就是利用xml或java编码获得资源来构建SqlSessionFactory对象,构建成功就失去了存在的意义,将其回收。所以它的生命周期只存在于方法的局部。

3.2 SqlSessionFactory

​ SqlSessionFactory的作用是创建SqlSession,而SqlSession就是一个会话,相当于JDBC中的Connection对象,每次访问数据库都需要通过SqlSessionFactory创建SqlSession,所以SqlSessionFactory应该在MyBatis应用的整个生命周期中。我们使每一个数据库只对应一个SqlSessionFactory(单例模式)。

3.3 SqlSession

​ SqlSession是一个会话,相当于JDBC的一个Connection对象,它的生命周期应该是在请求数据库处理事务的过程中。是一个线程不安全的对象,涉及多线程时格外当心。此外,每次创建的SqlSession都必须及时关闭它。

3.4 Mapper

​ Mapper是一个接口,没有任何实现类,其作用是发送sql,返回我们需要的结果,或者执行sql修改数据库数据,因此它也因该在一个SqlSession事务方法之内,是一个方法级别的东西。就如同 JDBC中的一条sql语句的执行,它的最大范围和SqlSession是相同的。

Tips: 根据核心组件封装工具、形成SqlSession使用模板
 public class MyBatisUtil {
     private static SqlSessionFactory build =null;
     static {
         try {  //使用MyBatis的Resources加载资源获得输入流,构建工厂
             InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
             build = new SqlSessionFactoryBuilder().build(inputStream);
         } catch (IOException e) {
             throw new RuntimeException("资源文件加载失败!");
         }
     }
     //使用工厂生产sqlSession 
     public static SqlSession openSession(){
         return build.openSession();
     }
 }

SqlSession使用方法

//1.定义sqlSession
SqlSession sqlSession = null;
try {
    sqlSession = openSession();
    //2.获取映射器
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //3.some code like 'User u = mapper.findById(id);'
    //4.sqlSession不提交默认回滚!增删改需格外注意!
    sqlSession.commit();
} catch (Exception e) {
    throw new RuntimeException(e);
} finally {
    if (sqlSession != null) {
        sqlSession.close();
    }
}

三:映射器

1.映射器元素简介

我们可以在映射器中定义哪些元素,以及它们有何作用呢?

元素名称作用
insert定义插入语句
delete定义删除语句
update定义修改语句
select定义查询语句
parameterMap定义参数映射关系
resultMap提供从数据库结果集到POJO映射规则
cache配置当前命名空间的缓存配置(二级缓存)
sql定义部分sql,各个地方都可引用
cache-ref引用其他命名空间的缓存配置

在各个元素当中又有相当多的属性配置项,这里不多赘述,通过下一节掌握常用的内容即可。这里特别说明sql元素的使用:

<sql id="user_columns">  <!-- 此处定义后,处处使用,尤其字段多的时候 -->
    id, name, password   
</sql>
<select ....>
    select <include refid="user_columns"/> from users where uid=#{id}
</select>

2.简单CRUD操作

2.1添加用户
<!-- 1.添加用户 -->
<insert id="add" parameterType="User">
    INSERT into users (name,password) VALUES (#{name},#{password});
</insert>
2.2添加用户并返回数据库中的主键
<!-- 2.添加用户,获取数据库生成的主键值(需数据库具备主键自增功能) -->
<insert id="add" parameterType="User" useGeneratedKeys="true" keyProperty="uid">
    insert into users (name,password) values(#{name},#{password});
</insert>
<!-- 3.添加用户,获取数据库生成的主键:数据库有无自动增长能力都可以-->
<insert id="add" parameterType="User">
    <selectKey keyColumn="uid" keyProperty="uid" resultType="int" order="AFTER">
        select last_insert_id();
    </selectKey>
    insert into users (name,password) values(#{name},#{password});
</insert>
2.3修改/删除用户
<!-- 4.修改/删除用户 -->
<update id="update" parameterType="User">
    update users set name=#{name},password=#{password} where uid=#{uid};
</update>
<delete id="delete" >
    delete from users where uid=#{uid};
</delete>
2.4查询用户
<!-- 5.查询所有的用户 -->
<!-- 定义查询结果映射规则(结果集映射可以用别名) -->
<resultMap id="userMap" type="User">
    <id column="id" property="uid"></id>
    <result column="姓名" property="name"></result>
    <result column="password" property="password"></result>
</resultMap>
<!-- 查询语句 -->
<select id="findAll" resultMap="userMap">
    select uid as id,name as '姓名',password from users;
</select>
<!--6.根据用户id查询用户(单个参数)-->
<select id="findById" parameterType="int" resultType="User">
    select uid,name,password from users where uid=#{uid};
</select>
<!-- 7.根据用户名和密码查询用户(接口定义方法参数时@Param(" ")进行指定,否则多个参数时
默认使用 arg0,arg1   或param1,param2来映射) -->
<select id="findByNamePassword" resultType="User">
    select uid,name,password from users where name=#{name} and password=#{password};
</select>
<!-- 8.根据用户实体对象查询用户 -->
<select id="findByUser" parameterType="User" resultType="User">
    select uid,name,password from users where name=#{name};
</select>
<!-- 9.根据用户名进行模糊查询 -->
<select id="findUsersLikeName" resultType="User">
    select uid,name,password from users where name like concat("%",#{name},"%");
</select>

四:动态sql和高级查询

1.动态sql

​   MyBatis的动态sql包含这些元素:if | choose(when ohterwise) |trim(where set) | foreach ,通过这些元素来动态组装sql语句,主要是增改查操作。*(实际开发中,严禁使用select * 操作。这里为了简便使用select 演示)!

1.1使用 if,实现动态sql,完成查询操作
<!-- 1.使用if,实现动态sql,完成查询操作 -->
<select id="findByCondition" parameterType="user" resultType="user">
    select uid,name,password,email from users where 1 = 1
    <if test="name != null and name !=''">
        and name like concat("%",#{name},"%")
    </if>
    <if test="password != null and password != '' ">
        and password = #{password}
    </if>
</select>
1.2使用if,实现动态sql,完成更新操作
<!-- 2.使用if,实现动态sql,完成更新操作 -->
<update id="updateUser" parameterType="user">
   update users set
   <if test="name != null and name != '' ">
       name=#{name},
   </if>
   <if test="password != null and password != '' ">
       password=#{password},
   </if>
   uid=#{uid} where uid=#{uid}; <!-- 保证任何情况下的sql完整 -->
</update>
1.3使用if,实现动态sql,完成添加操作
<!-- 3.使用if,实现动态sql,完成添加操作 -->
<insert id="addUser" parameterType="user">
    insert into users (name,
    <if test="password != null and password != '' ">
        password,
    </if>email,phoneNumber,birthday) values(#{name},
    <if test="password != null and password != '' ">
        #{password},
    </if>#{email},#{phoneNumber},#{birthday});
</insert>
1.4使用choose when otherwise,实现动态sql,完成查询操作
<!-- 4.使用choose when otherwise,实现动态sql,完成查询操作 -->
<select id="findByCondition" parameterType="user" resultType="user">
    select * from users where 1 = 1 <!-- 动态组装准备 -->
    <choose>
        <when test="name != null and name != '' ">
            and name like concat("%",#{name},"%");
        </when>
        <otherwise>
            and 1 = 2; <!-- 动态否决 -->
        </otherwise>
    </choose>
</select>
1.5使用if和where,实现动态sql,完成查询操作 ★★★
<!-- 5.使用if和where,实现动态sql,完成查询操作 -->
<select id="findByCondition" resultType="user" parameterType="user">
    select * from users
    <where>  <!-- 至少有一个if执行时才会加上where关键字并去掉紧跟后面的and|or关键字 -->
        <if test="name != null and name != '' ">
            and name like concat("%",#{name},"%")
        </if>
        <if test="password != null and password != '' ">
            and password=#{password}
        </if>
    </where>
</select>
1.6使用if和set,实现动态sql,完成更新操作 ★★
<!-- 6.使用if和set,实现动态sql,完成更新操作 -->
<update id="updateUser" parameterType="user">
    update users
    <set>   <!-- set元素会去掉最后一个,号 -->
        <if test="name != null and name != '' ">
            name=#{name},
        </if>
        <if test="password != null and password != '' ">
            password=#{password},
        </if>
        uid=#{uid},
    </set>
    where uid=#{uid};
</update>
<!-- trim元素的使用 -->
<trim prefix="where" prefixOverrides="and|or"></trim> <!-- 等同与where元素 -->
<trim prefix="set" suffixOverrides=","></trim> <!-- 等同与set元素 -->
1.7使用foreach,实现动态sql,完成根据id集合、数组等的查询操作
<!-- 7.使用foreach,实现动态sql,完成根据id list列表的查询操作 -->
<select id="findByIds" resultType="user">
    select * from users where uid in
    <foreach collection="collection" open="(" close=")" separator="," item="uid">
        #{uid}
    </foreach>
</select>
<!-- foreach中的collection值取决于要遍历的对象类型(mybatis内部做判断后默认的)
 List : 可取 collection或list
 Set  : 取 collection
 Array: 取 array
 Map  : 取 _parameter   (用map无意义,遍历的依旧是value)
上述默认引用都可以在接口方法中通过@Param(“  ”)覆盖掉!
-->
1.8bind元素

bind元素的作用是通过OGNL表达式自定义一个上下文变量,这样更方便我们使用。在进行模糊查询的时候,如果是MySQL数据库,我们常用concat函数用“%”和参数连接。然而在Oracle数据则是用连接符号“||”。这样sql就需要提供两种形式去实现。用bind元素,我们就不必使用数据库语言,只要使用MyBatis的语言即可与所需参数相连。

<select id="findByCondition" parameterType="user" resultType="user">
    <!-- 使用bind定义上下文变量 -->
    <bind name="pattern" value="'%' + name + '%' "/>
    select uid,name,password,email from users where 1 = 1
    <if test="name != null and name !=''">
       <!-- and name like concat("%",#{name},"%") -->
        and name like #{pattern}
    </if>
    <if test="password != null and password != '' ">
        and password = #{password}
    </if>
</select>

2.高级查询(多表查询)

2.1一对多关联查询
<!-- 1.使用多表查询,完成一对多关联查询及映射 -->
    <!-- user结果集封装,可以通过继承重复使用 -->
<resultMap id="userMap" type="user">
    <id column="uid" property="uid" />
    <result column="name" property="name"/>
    <result column="password" property="password"/>
</resultMap>
    <!-- loginInfo结果集,继承user结果集完整数据 -->
<resultMap id="userLoginInfoMap" extends="userMap" type="user">
    <!-- 使用collection映射多的一方,ofType指定集合中的数据类型 -->
    <collection property="loginInfos" ofType="loginInfo">
        <id column="lid" property="lid"/>
        <result column="ip" property="ip"/>
        <result column="loginTime" property="loginTime"/>
    </collection>
</resultMap>
    <!-- 定义查询语句 -->
<select id="findAllUsers" resultMap="userLoginInfoMap">
    select * from users u left join login_infos li on u.uid = li.uid;
</select>
2多对一关联查询(别名映射|resultMap映射|resultMap结合association映射)
<!-- 2.多对一,采用别名映射关联关系 -->
<select id="findAllLoginInfos" resultType="loginInfo">
    select li.*,
    u.uid "user.uid",
    u.name "user.name",
    u.password "user.password"
    from login_infos li,users u
    where li.uid = u.uid;
</select>
<!-- 3.多对一,采用resultMap进行结关联关系的映射 -->
<resultMap id="userMap" type="loginInfo">
    <id column="uid" property="user.uid"/>
    <result column="name" property="user.name"/>
    <result column="password" property="user.password"/>
</resultMap>    
<!-- 这里的resultMap继承关系最好和POJO中的关联关系保持一致,便于理解
     这里不一致,但也可以运行
 -->
<resultMap id="userLoginInfoMap" extends="userMap" type="loginInfo">
    <id column="lid" property="lid"/>
    <result column="ip" property="ip"/>
    <result column="loginTime" property="loginTime"/>
</resultMap>
<select id="findAllLoginInfos1" resultMap="userLoginInfoMap">
    select * from users u,login_infos li where u.uid=li.uid;
</select>
<!-- 4.多对一,使用resultMap结合association进行关联关系的映射 -->
<resultMap id="loginInfoMap" type="loginInfo">
    <id column="lid" property="lid"/>
    <result column="ip" property="ip"/>
    <result column="loginTime" property="loginTime"/>
</resultMap>
<!-- 这里的resultMap继承关系和POJO的关联关系保持了一致,即LoginInfo下有User属性 -->
<resultMap id="loginInfoUserMap" extends="loginInfoMap" type="loginInfo">
    <association property="user" javaType="user">
        <id column="uid" property="uid"/>
        <result column="name" property="name"/>
        <result column="password" property="password"/>
    </association>
</resultMap>
<select id="findAllLoginInfos2" resultMap="loginInfoUserMap">
    select * from users u,login_infos li where u.uid=li.uid;
</select>
2.3多对多关联查询
<!-- 13.使用多表查询,完成多对多查询,查找所有的用户及其角色 -->
<!-- 注意:为了避免冗余,这里继承了2.2中的resultMap -->
 <resultMap id="userRoleMap" extends="userMap" type="user">
     <collection property="roles" ofType="role">
         <id column="rid" property="rid"/>
         <result column="name" property="name"/>
         <result column="description" property="description"/>
     </collection>
 </resultMap>
<!-- 多对多主要在sql编写上,需要借助中间表 -->
 <select id="findAllUsers" resultMap="userRoleMap">
     select * from users u left join users_roles ur 
     on u.uid=ur.uid inner join roles r on ur.rid=r.rid;
 </select>

五:嵌套查询和延迟加载

1.加载策略

​ 在关联查询时,对于关联的一方是否查询出来,要根据业务需求而定。不能通过编码方式进行策略的改变,而应该通过修改配置文件改变加载策略。可以使用嵌套查询(分步查询)。

2.嵌套查询

2.1根据多的一方,嵌套查询少的一方
<!-- 1.嵌套查询,使用reultMap结合association使用引用的mapper.xml进行查询 -->
<resultMap id="loginInfoMap" type="loginInfo">
    <id column="lid" property="lid"/>
    <result column="ip" property="ip"/>
    <result column="loginTime" property="loginTime"/>
</resultMap>
<resultMap id="loginInfoUserMap" extends="loginInfoMap" type="loginInfo">
    <!-- 解决user属性: property:属性
        column:查询依据,也是当前查询表的外键
        select:指向根据外键查询的xml唯一映射
    -->
    <association property="user" column="uid" 
                 select="cn.dintalk.UserMapper.findById"/>
</resultMap>
<select id="findAllLoginInfos3" resultMap="loginInfoUserMap">
    select * from login_infos;
</select>

<!-- 在association中,select指向的是另一个Mapper.xml文件中的映射(根据命名空间和id) -->
<!-- UserMapper.xml中  14.嵌套查询之 根据uid查询用户 -->
<select id="findById" resultType="user">
    select * from users where uid = #{uid};
</select>
2.2根据少的一方,嵌套查询多的一方
<!-- 2.使用嵌套查询,可通过懒加载优化sql,查询所有的用户及其日志信息 -->
<!-- 为了简便,这里继承了上述的id为userMap的resultMap -->
<resultMap id="userLoginInfoMap" extends="userMap" type="user">
    <collection property="loginInfos"  column="uid" 
                select="cn.dintalk.dao.LoginInfoMapper.findAllLoginInfos"/>
</resultMap>
<select id="findAllUser" resultMap="userLoginInfoMap1">
    select * from users;
</select>
<!-- 同理,在collection中,select指向的是另一个Mapper.xml文件的映射 -->
<!--LoginInfoMapper.xml中  5.根据用户id查询所有的登录信息 -->
<select id="findAllLoginInfos" resultType="loginInfo">
    select * from login_infos where uid=#{uid};
</select>

3.配置延迟加载

3.1全局配置,修改mybatis.xml主配置文件
<!-- 2.配置延迟加载,即sql优化 -->
<settings>
    <!-- 启用懒加载策略 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 覆盖掉延迟加载的触发方法 -->
    <setting name="lazyLoadTriggerMethods" value=""/>
</settings>

启用延迟加载后,mybatis默认有toString、equals等4个触发加载的方法。我们也可以将其覆盖掉。

延迟加载,即用到关联数据的时候再去查,不用就不查。(service层中会有很多方法调用dao方法,根据service层中的实际需求动态调整加载策略,高效利用资源!)

3.2每个association和collection都有fetchType属性
该属性的值会覆盖掉全局配置

fetchType=“lazy”(默认) | eager

  • lazy : 支持延迟加载

  • eager : 立即加载

六:事务控制及数据源

1.事务控制

默认情况下:MySql的事务是自动提交的。

​ 通过 JDBC 可以手动控制:

​ Connection.setAutoCommit(false);

​ Connection.commit();

​ Connection.rollback();// 开启事务后,未提交会自动回滚!
MyBatis中: mybatis-config.xml 作如下配置
<transactionManager type="JDBC"></transactionManager>

相当于使用 JDBC 进行事务控制:(增删改时不提交会自动回滚!)

获取SqlSession时:SqlSessionFactory.openSession(); // 手动控制事务 ★

​ SqlSessionFactory.openSession(true); //自动提交事务

2.数据源

2.1mybatis内置数据源

mybatis内置了三种数据源:

UNPOOLED :不带有池(连接池)|学习时用

POOLED : 带有池的 | 实际生产环境使用

JNDI : mybatis提供的JndiDataSourceFactory来获取数据源

2.2内部原理

POOLED对应的是PooledDataSource数据源,PooledDataSourceFactory用来生产带有池的数据源。

UNPOOLED对应的是UnpooledDataSource数据源,UnpooledDataSourceFactory用来生产不带有池的数据源。

2.3使用Druid等第三方数据源(以Druid为例)
第一步:引入Druid的Jar包或数据源
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.14</version>
</dependency>

第二步:编写工厂类,用来产生Druid的数据源,一般选择继承UnpooledDataSourceFactory

public class DataSourceFactory extends UnpooledDataSourceFactory{
    public DataSourceFactory(){
        this.dataSource = new DruidDataSource();//创建druid数据源
    }
}

第三步:在mybatis-config.xml中进行配置

<!--1.类别名的配置 -->
<typeAliases>
    <typeAlias type="cn.dintalk.dataSource.DataSourceFactory" alias="DRUID"/>
</typeAliases>
<environments default="mysql">
   <environment id="mysql">
       <transactionManager type="JDBC"></transactionManager>
       <!-- 2.配置druid数据源 -->
       <dataSource  type="DRUID">
           <!-- 3.配置数据库连接:name由数据源中的setXXX而定,value是外部配置的key -->
           <property name="driverClassName" value="${jdbc.driver}"></property>
           <property name="url" value="${jdbc.url}"></property>
           <property name="username" value="${jdbc.username}"></property>
           <property name="password" value="${jdbc.password}"></property>
       </dataSource>
   </environment>
</environments>

七:MyBatis的缓存

1.系统缓存

MyBatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存。

1.1一级缓存

​ 一级缓存只是相对于同一个SqlSession而言的。使用SqlSession第一次查询后,MyBatis会将其放在缓存中,以后再查询时,如果没有声明需要刷新,且缓存未超时的情况下,SqlSession都只会取出当前缓存的数据,而不会再次发送Sql到数据库。

1.2二级缓存

​ 二级缓存是在SqlSessionFactory层面上的,可以将缓存提供给各个SqlSession对象共享。

开启二级缓存配置
mybatis-confi.xml文件中(默认开启,可忽略)
<settings>  
  <!-- 二级缓存配置(默认开启,此行可省略) -->
  <setting name="cacheEnabled" value="true"/>
</settings>

Mapper.xml文件中

<mapper namespace="cn.dintalk.dao.UserMapper">
    <cache/>  <!-- 开启二级缓存,使用默认配置 -->
</mapper>
<!-- 使用默认配置意味着:
映射语句文件中的所有select语句将会被缓存。
映射语句文件中的所有insert、update和delete语句会刷新缓存。
缓存使用默认的Least Recently Used(LRU,最近最少使用的)回收策略。
缓存会存1024个列表集合或对象(无论查询方法返回什么)
缓存会被视为是read/write(可读可写)的缓存
-->

Tips:

  • 一级缓存中存放的是对象本身,是同一个对象!

  • 二级缓存中存放的是对象的拷贝,对象所属类必须实现jav.io.Serializable接口!

配置缓存
<cache  evicition="LRU" flushInterval="100000" size="1024" readOnly=true/>
  • eviction: 代表的是缓存回收策略,目前MyBatis提供以下策略:

    ​ (1)LRU, 最近最少使用的,移除最长时间不用的对象。

    ​ (2)FIFO, 先进先出,按对象进入缓存的顺序来移除它们。

    ​ (3)SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象。

    ​ (4)WEAK,弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

  • flushInterval: 刷新间隔时间,单位为毫秒。

  • size: 引用数目,代表缓存最多可以存储多少个对象。

  • readOnly: 只读,意味着缓存数据只读。

2.自定义缓存

​   系统缓存是MyBatis应用机器上的本地缓存,我们也可以使用缓存服务器来定制缓存,如比较流行的Redis缓存。我们需要实现MyBatis为我们提供的接口org.apache.ibatis.cache.Cache,缓存接口简介:

//获取缓存编号
String getId();
//保存key值缓存对象
void putObject(Object key,Object value);
//通过key获取缓存对象
Object getObject(Object key);
//通过key删除缓存对象
Object removeObject(Object key);
//清空缓存
void clear();
//获取缓存对象大小
int getSize();
//获取缓存的读写锁
ReadWriterLock getReadWriterLock();

由于每种缓存都有其不同的特点,上面的接口都需要我们去实现。假设我们已经有一个实现类:cn.dintalk.MyCache。则配置如下:

<cache type="cn.dintalk.MyCache"/>

完成上述配置,就能使用自定义的缓存了。MyBatis也支持在缓存中定义常用的属性,如:

<cache type="cn.dintalk.MyCache">
  <property name="host" value="localhost"/>
</cache>

如果我们在MyCache这个类中增加setHost(String host) 方法,那么它在初始化的时候就会被调用,这样我们可以对自定义的缓存设置一些外部参数。

Tips: 我们也可配置Sql层面的缓存规则,来决定它们是否需要刷新或使用缓存。

<insert ...flushCache="true"/>
<delete ...flushCache="true"/>
<update ...flushCache="true"/>
<select ...flushCache="false" useCache="true"/>

八:附录-MyBatis常用配置及开发Tips

附录1:mybatis-config.xml常用配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 1.引入外部的配置文件 -->
    <properties resource="jdbc.properties"/>
    <!-- 2.配置延迟加载,即sql优化 -->
    <settings>
        <!-- 启用懒加载策略 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 覆盖掉延迟加载的触发方法 -->
        <setting name="lazyLoadTriggerMethods" value=""/>
        <!-- 二级缓存配置(默认开启,此行可省略) -->
        <!-- 使用二级缓存,在对应的mapper.xml中加入cache即可 -->
        <!--<setting name="cacheEnabled" value="true"/>-->
    </settings>
    <!-- 3.类别名的配置 -->
    <typeAliases>
        <!-- 单个类的配置 -->
        <!--<typeAlias type="cn.dintalk.domain.User" alias="user"/>-->
        <!-- 配置druid数据源工厂类别名 -->
        <typeAlias type="cn.dintalk.dataSource.DataSourceFactory" alias="DRUID"/>
        <!-- 给包中所有的类配置默认别名, 即类名首字母小写-->
        <package name="cn.dintalk.domain"/>
    </typeAliases>
    <!-- 4.使用默认的环境配置(可以是多个) -->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 事务管理器,此处配置 为JDBC -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 数据源配置,此处配置为 POOLED-->
            <!--<dataSource  type="POOLED">-->
            <!-- 配置druid数据源 -->
            <dataSource  type="DRUID">
                <!-- 配置数据库连接:name由数据源中的setXXX而定,value是外部配置的key -->
                <property name="driverClassName" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 5.注册映射文件 -->
    <mappers>
        <!-- 指定资源文件路径 -->
        <!--<mapper resource="cn/dintalk/dao/UserMapper.xml"></mapper>-->
        <!--<mapper resource="cn/dintalk/dao/LoginInfoMapper.xml"></mapper>-->
        <!-- 基于Mapper接口的开发:指定类名-->
        <!--<mapper class="cn.dintalk.dao.UserMapper"/>-->
        <!-- 指定基于Mapper接口开发的包:(需类名和xml文件名一致,包名一致)-->
        <package name="cn.dintalk.dao"/>
    </mappers>
</configuration>
附录2:Mapper.xml头约束
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.dintalk.dao.UserMapper">
    <cache/> <!-- 开启二级缓存 -->
</mapper>
Wider Face+YOLOV7人脸检测 使用Wider Face数据集训练YOLOV7 阅读详情

相关推荐

一文解读DeepSeek训练数据集

本文重点以DeepSeek为例,详细介绍预训练数据集相关内容。大语言模型LLM(如DeepSeek、ChatGPT、文心一言等)的“智慧”源于它们学习的海量数据集。简单来说,数据集就是模型的“知识库”,通常由互联网公开的文本、图片、视频等。这些数据需满足两个特点:规模大和多样性。规模大是指数据量可达千亿级词汇,让模型学习复杂规律;多样性则涵盖多领域(如科技、文学)、多语言、多形式(对话、新闻),帮助模型适应不同场景。例如,训练数据中既有百科知识,也有日常对话,模型才能既解答专业问题,又能闲聊。

u013891230的博客 7090

MyBatis -- 必知必会

  MyBatis的前身是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。2013年11月迁移到GitHub,因此目前MyBatis是由GitHub维护的。 ​ 同样作为持久层框架的Hibernate在前些年非常的火,它在配置了映射文件和数据库连接文件后就可以通过...

weixin_30546189的博客 666

高通Camera HAL3调试实战:如何用camxoverridesettings.txt高效抓取日志与dump图像数据

本文深入探讨了高通Camera HAL3调试中camxoverridesettings.txt文件的高效应用,重点介绍了如何通过该文件精准控制日志输出级别与dump图像数据,帮助开发者快速定位移动影像系统中的问题。文章详细解析了日志分级配置、图像数据捕获技巧及典型问题排查流程,为高通Camera HAL3项目开发提供了实用技术点。

weixin_30315905的博客 864

mybatis字符串比较小结(equals)

mybatis字符串比较

haidian_fengyu的专栏 1万+

全球AI算力最强公司分析报告

全球AI算力最强公司分析报告显示,Google凭借自研TPU技术和庞大数据中心网络位居榜首,拥有约100万至150万块等效H100 GPU算力。微软、Meta和亚马逊紧随其后,分别拥有75万、55万和25万块等效H100 GPU。中国企业中,百度、阿里巴巴和腾讯表现突出,华为在国产AI芯片领域领先。技术指标上,NVIDIA H100相比A100性能显著提升,但功耗也大幅增加。未来AI算力需求将持续激增,预计2028年全球市场将超2000亿美元。新兴挑战者如xAI可能改变竞争格局。

MyySophia的博客 5721

Python量化交易入门:天勤量化TqSdk保姆级教程(含避坑指南)

本文提供Python量化交易入门指南,重点介绍天勤量化TqSdk的使用方法,包括环境配置、核心API实战、策略开发技巧及实盘部署。教程涵盖中国期货市场,帮助个人投资者快速掌握量化交易技术,避开常见陷阱。

weixin_29065791的博客 836

MyBatis SqlSession事务与批量执行正确方式(默认不生效)

某些情况下会使用MyBatis的SqlSessionFactory.openSession()方法获取SqlSession对象,再进行数据库操作,但默认情况下SqlSession的事务与批量执行均不生效,假如希望使用SqlSession时事务或批量执行能够生效,则需要进行额外的处理。

adrninistrat0r的博客 1万+

Unity热更实战:用YooAsset+HybridCLR实现小游戏资源与代码双更新(含避坑清单)

本文详细介绍了Unity小游戏开发中如何通过YooAsset与HybridCLR实现资源与代码双热更新方案。内容涵盖环境配置、架构设计、微信小游戏专项优化、热更代码工程化实践及真机调试技巧,帮助开发者解决审核周期长、紧急修复等痛点,提升更新效率与稳定性。

weixin_42520025的博客 506

mybatis SqlSessionFactory . openSession()方法执行过程

//false: 不自动提交 SqlSession sqlSession = factory.openSession(false); public class DefaultSqlSessionFactory implements SqlSessionFactory { //DefaultSqlSessionFactory 中唯一成员变量 private final Configuration configuration; @Override public SqlSession openSe

weixin_42490383的博客 9912

ESP32-CAM与Thonny的完美搭配:从烧录到通信的完整流程

本文详细介绍了如何将ESP32-CAM与Thonny IDE完美结合,从固件烧录到通信测试的完整流程。通过硬件连接、MicroPython固件烧录、Thonny环境配置以及摄像头功能开发等步骤,帮助开发者快速搭建高效的物联网开发环境,实现图像采集与无线通信功能。

tomato的博客 1128

【Python爬虫系列】_005.浏览器开发者工具(详解)

Elements(元素)分析当前页面节点,用来辅助书写BS或者XPath这里面的数据与源代码有区别,不一定准确(避坑)Console(控制台)这个除了查看错误信息、打印调试信息(console.log())、写一些测试脚本以外,还可以当作Javascript API查看用例如我想查看console都有哪些方法和属性,我可以直接在Console中输入"console"并执行后续学js逆向的时候需要用到Sources(源代码)与在网页页面,鼠标右键——查看网页源代码 内容一致。

weixin_50296259的博客 423

如何利用AI技术优化原生应用的用户体验

打开手机,你手机里可能装着100+个原生应用(iOS/Android独占安装包的应用),但真正“常用”的可能只有10个。静态界面的“信息过载”:传统应用依赖固定的UI模板(如“首页-分类-购物车”),用户需要主动搜索才能找到目标内容,新手往往在复杂菜单中迷失;被动响应的“交互割裂”:用户必须通过点击、滑动触发操作,应用无法预判需求(比如下雨天不会主动推送雨伞商品);“一刀切”的服务模式:新用户和老用户、学生和白领看到的界面几乎相同,缺乏“量身定制”的温度。AI的本质。

Agentic AI人工智能与大数据正在引领一场新智能科技革命。 1073

Codev与Zemax相互转化

Codev与Zemax相互转化

weixin_72050316的博客 1046

mysql知识点+map_那些你必须知道的MyBatis实用知识点

一、MyBatis简介MyBatis的前身是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。2013年11月迁移到GitHub,因此目前MyBatis是由GitHub维护的。​同样作为持久层框架的Hibernate在前些年非常的火,它在配置了映射文件和数据库连接文件后就可以...

weixin_39971435的博客 163

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

关于MyBatis你必须知道的知识点,MyBatis概念-使用详解!

1、什么是MyBatis (1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。 (2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 (3)通过xml 文件或注解的方式将要执行的各种 statemen

weixin_48655626的博客 374

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

MyBatis 核心知识点总结

定位:一个优秀的 数据持久层框架(ORM:Object Relational Mapping)。特点:半自动化。不同于 Hibernate 的全自动 SQL 生成,MyBatis 需要开发者自己编写 SQL,因此更加灵活,可以编写复杂、高性能的 SQL。核心思想:SQL 与程序代码分离,通过配置实现 SQL 的灵活管理和优化。1. 首选 Mapper 接口代理开发,避免硬编码和编写实现类。2. 使用 `#{}` 预编译方式来防止 SQL 注入。

2301_80047006的博客 1974

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Mybatis知识点

持续推出mybatis的知识点和问题

菜就多练! 1089

Mybatis知识点整理

1、Mybatis概述 1.1 JDBC编程 1.2.说说你对Mybatis的了解 1.Mybatis 基于java的持久层框架,它的内部封装了JDBC,让开发人员只需要关注SQL语句本身,不需要花费精力在驱动的加载、连接的创建、Statement的创建等复杂的过程。 2.Mybatis通过XML或注解的方式将要执行的各种的statement配置起来,并通过java对象和statement中的sql的动态参数进行映射生成最终执行的SQL语句,最后由mybatis框架执行SQL,并将结果直接

你好啊cbw 1万+

知识点整理,MyBatis面试题

什么是Mybatis? 1、Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时 只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性 能,灵活度高。 2、MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数 据库中的记...

BoCong-Deng的博客 1万+

MyBatis 知识点

{}

sswwsm的博客 671

Mybatis面试知识点总结

Mybatis面试知识点总结: 1. 介绍一下Mybatis框架。答:Mybatis是一个优秀的持久层框架。它和Hibernate一样,对jdbc操作数据库的过程进行了封装。它本来叫iBatis,是apache公司的一个开源项目,但在2010年的时候迁移到了Google公司,并改名为Mybatis。 2. 使用jdbc操作数据库存在的缺点?答:1.频繁的创建连接和释放资源,造成系统资源浪费。   ...

lz1170063911的博客 3264

MyBatis核心知识点解析

场景问题:在一个传统的Java Web项目中,开发人员常常需要手动编写SQL语句与数据库进行交互,同时管理SQL映射文件和Java对象之间的映射关系。随着项目规模的扩大,这种手动管理方式不仅增加了代码的复杂度,而且容易出错,导致维护成本高。为了解决这一问题,MyBatis框架应运而生,它通过半自动化的方式简化了数据库操作,提高了开发效率。知识点重要性:介绍MyBatis概述:MyBatis简介这一知识点,是因为它是理解MyBatis框架的基础。

MoneyHacksPro的博客 1028

MyBatis常见知识点

原理是,MyBatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签尚未解析到,尚不存在,此时,MyBatis 会将 A 标签标记为未解析状态,然后继续解析余下的标签,包含 B 标签,待所有标签解析完毕,MyBatis 会重新解析那些被标记为未解析的标签,此时再解析 A 标签时,B 标签已经存在,A 标签也就可以正常解析完成了。答:能,MyBatis 不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把。映射方式为自定义一个。

2301_80148369的博客 2354

Mybatis知识点总结

mybatis知识点总结 复习用

weixin_49013768的博客 392
上一篇: Spring Boot 集成 Memcached
下一篇: Redis的五大数据类型实现原理
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值