springboot之mybatis的简单理解与使用

  • mybatis

    mapper映射模式

    1. 目录结构
      在这里插入图片描述

    2. mybatis配置文件MybatisConfig.xml

      <!--    development1使用的环境id-->
          <environments default="development1">
      
      <!--        配置环境id 可多个-->
              <environment id="development1">
      <!--            事务管理-->
                  <transactionManager type="JDBC">
      
                  </transactionManager>
      
      <!--            数据源 POOLED(池)-->
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
                      <property name="username" value="root"/>
                      <property name="password" value="root"/>
                  </dataSource>
              </environment>
          </environments>
      
      <!--    映射文件路径-->
          <mappers>
              <mapper resource="mapper/user.xml"></mapper>
              <mapper resource="mapper/role.xml"></mapper>
          </mappers>
      </configuration>
      
    3. 映射文件user.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="user">
      
          <resultMap id="resultUser" type="domain.entity.User">
              <id column="id" property="id"></id>
              <result column="user_name" property="userName"></result>
              <result column="name" property="name"></result>
              <result column="brithday" property="brithday"></result>
              <result column="age" property="age"></result>
          </resultMap>
      
          <insert id="addUser" parameterType="domain.entity.User">
              insert into user(user_name,name,brithday,age) values (#{userName},#{name},#{brithday},#{age})
          </insert>
      
          <update id="updateUser" parameterType="domain.entity.User">
              update user set user_name=#{userName},age=#{age} where id=#{id}
          </update>
      
          <select id="selectUserAll" resultMap="resultUser">
              select * from user
          </select>
      
          <select id="selectUser" parameterType="long" resultMap="resultUser">
              select * from user where id=#{id}
          </select>
          
          <delete id="deleteUser" parameterType="long">
              delete from user where id=#{id}
          </delete>
      
      </mapper>
      
      <?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="role"> 	//在开发中,可直接映射到XXXmapper接口
      
          <resultMap id="resultRole" type="domain.entity.Role">
              <id column="id" property="id"></id>
              <result column="role_name" property="roleName"></result>
              <result column="role_code" property="roleCode"></result>
          </resultMap>
      
          <select id="selectUserAll" resultMap="resultRole">
              select * from role
          </select>
      </mapper>
      

      namespace="domain.entity.User"为别名,假如两个映射文件里有同名,则就不知道找哪个了,两个select标签名一致,如果不使用别名会报错

    4. #、$

      • #{},#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。

      • , {} , 将传入的数据直接显示生成在sql中


        • #方式能够很大程度防止sql注入,$方式无法防止Sql注入。

        • $方式一般用于传入数据库对象,例如传入表名。

        • 从安全性上考虑,能使用#尽量使用#来传参,因为这样可以有效防止SQL注入的问题。

    5. 测试代码

      package domain.entity;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.ResultHandler;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      import org.junit.jupiter.api.Test;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.Date;
      import java.util.List;
      
      public class UserTest {
      
      
          User user=new User();
      
      
          @Test
          public void uTest(){
              user.setAge(26);
      
              System.out.println(user.toString());
          }
      
          public static SqlSessionFactory getSqlss(){
              String resource="MybatisConfig.xml";
              SqlSessionFactory sqlSessionFactory=null;
              try {
                  InputStream inputStream=Resources.getResourceAsStream(resource);
                 sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
                  return sqlSessionFactory;
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              return sqlSessionFactory;
      
          }
      
          @Test
          public void addUserTest(){
              user.setUserName("王1");
              user.setName("1号");
              user.setBrithday(new Date());
              user.setAge(19);
      
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
              sqlSession.insert("addUser",user);
      
              sqlSession.commit();
              //System.out.println(UserTest.getSqlss());
      
          }
      
          @Test
          public void updateUserTest(){
      
              user.setId(2L);
              user.setUserName("王2");
              user.setName("2号");
              user.setBrithday(new Date());
              user.setAge(29);
      
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
              sqlSession.insert("updateUser",user);
      
              sqlSession.commit();
              //System.out.println(UserTest.getSqlss());
      
          }
      
      
          @Test
          public void selectUserAllTest(){
      
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
      
              List<User> userList=sqlSession.selectList("domain.entity.User.selectUserAll");
      
              System.out.println(userList.toString());
      
          }
      
          @Test
          public void selectUserTest(){
      
              Long id=3L;
      
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
      
              User user1=sqlSession.selectOne("selectUser",id);
      
              System.out.println(user1.toString());
      
          }
      
      
          @Test
          public void deleteUserTest(){
      
              Long id=3L;
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
              sqlSession.delete("deleteUser",id);
      
              sqlSession.commit();   //增删改必须提交
              //System.out.println(UserTest.getSqlss());
      
          }
      
          
          //别名一致测试
          @Test
          public void selectRoleAllTest(){
      
              SqlSession sqlSession=UserTest.getSqlss().openSession();
      
      
              List<User> userList=sqlSession.selectList("domain.entity.Role.selectUserAll");
      
              System.out.println(userList.toString());
      
          }
      }
      
      

    mapper代理模式

    1. 其他配置不变,改变的是不需要使用名字取获取对于的xml映射文件

    2. mapper接口

      package infra.mapper;
      
      import domain.entity.Role;
      
      import java.util.List;
      
      public interface RoleMapper {
      
          public List<Role> selectRoleAll();
      }
      
      
    3. 对应的映射文件

      <?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="infra.mapper.RoleMapper">
      
          <resultMap id="resultRole" type="domain.entity.Role">
              <id column="id" property="id"></id>
              <result column="role_name" property="roleName"></result>
              <result column="role_code" property="roleCode"></result>
          </resultMap>
      
          <select id="selectRoleAll" resultMap="resultRole">
              select * from role
          </select>
      </mapper>
      

      namespace=“infra.mapper.RoleMapper”:这里不再是别名,而是对应mapper接口路径,完成接口与xml映射文件的绑定。在select标签中,id="selectRoleAll"为接口里面的方法名,这样一来就可以把方法和查询服务绑定在一起了

    4. 测试

      public static SqlSessionFactory getSqlss(){
              String resource="MybatisConfig.xml";
              SqlSessionFactory sqlSessionFactory=null;
              try {
                  InputStream inputStream=Resources.getResourceAsStream(resource);
                 sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
                  return sqlSessionFactory;
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              return sqlSessionFactory;
      
          }
      
      RoleMapper mapper=UserTest.getSqlss().openSession().getMapper(RoleMapper.class);
      //openSession()获取sqlSession
          @Test
          public void selectRoleAllTest1(){
      
      
              List<Role> userList=mapper.selectRoleAll();
      
              System.out.println(userList.toString());
      
          }
      
    5. 打包

      mvn clean install -Dmaven.test.skip=true -U 
      

      清理项目生产的临时文件,一般是模块下的target目录。同时执行模块安装命令 将打包的的jar/war文件复制到你的本地仓库中,供其他模块使用 -Dmaven.test.skip=true 跳过测试(同时会跳过test compile),而-U强制更新

动态sql

  1. <select id="selectUserIf" resultMap="resultUser">
        select * from user
        where
        <if test="ifId!=2L">
            id=3
        </if>
    </select>
    
    public User selectUserIf(@Param("ifId") Long ifId);
    
    @Test
    public void selectUserIfTest(){
    
    User user2=userMapper.selectUserIf(1L);
    
    System.out.println(user2.toString());
    //User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=null}
    
    }
    
  2. where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除.

    <select id="selectUserIf" resultMap="resultUser">
            select * from user
            <where>
                <if test="ifId!=2L">
                    or id=3
                </if>
                <if test="ifId!=2L">
                    or id=4
                </if>
            </where>
        </select>
    
     @Test
        public void selectUserIfTest(){
    
            List<User> user2=userMapper.selectUserIf(1L);
    
            System.out.println(user2.toString());
    //        [User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=null},
    //        User{id=4, userName='王4', name='1号', brithday=Tue Jul 13 13:09:46 CST 2021, age=17, roleList=null}]
    
        }
    
     select * from user where id=3 or id=4
    
  3. 条件控制标签、、组合使用

    <select id="selectUserIf" resultMap="resultUser">
            select * from user
            <where>
                <choose>
                    <when test="ifId!=2L">
                        id=3
                    </when>
                    <otherwise>
                        id=5
                    </otherwise>
                </choose>
            </where>
        </select>
    
    @Test
    public void selectUserIfTest(){
    
        List<User> user2=userMapper.selectUserIf(2L);
    
        System.out.println(user2.toString());
        //        [User{id=5, userName='王5', name='1号', brithday=Tue Jul 13 13:09:51 CST 2021, age=16, roleList=null}]
    
    }
    

    等同于if,等同于else ,也可以sql里的 then

  4. set标签用于update语句中,会自动去掉**’ ,’** (逗号)

    <update id="updateUser" parameterType="domain.entity.User">
        update user
        <set>
            <if test="id!=2L">
                ,user_name=#{userName}
            </if>
            <if test="id!=2L">
                ,age=#{age}
            </if>
        </set>
        <where>
            id=#{id}
        </where>
    
    </update>
    
    @Testpublic void updateUserTest11(){    user.setId(4L);    user.setUserName("王4");    user.setName("4号");    user.setBrithday(new Date());    user.setAge(24);    userMapper.updateUser(user);    UserTest.getSqlss().openSession().commit();}
    
  5. 常用于IN 语句

    collection:参数里面的集合名

    open: 开头自动拼接符号

    close:结束自动拼接符号

    separator:分隔符

    item:迭代的元素名,该参数为必选。

    index:迭代的序列号,在list和数组中,index是元素的序号,在map中,index是元素的key。

    <select id="countByUserList" resultType="_int" parameterType="list">
        select count(*) from users
        <where>
            id in
            <foreach item="item" collection="list" separator="," open="(" close=")" index="">
                #{item.id, jdbcType=NUMERIC}
            </foreach>
        </where>
    </select>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B93IvHb1-1630748441226)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis_foreach.png)]

  6. 一对一

    property:对应User类的哪个字段;javaType:这个字段的类型

    <resultMap id="resultUser" type="domain.entity.User">
        <id column="id" property="id"></id>
        <result column="user_name" property="userName"></result>
        <result column="name" property="name"></result>
        <result column="brithday" property="brithday"></result>
        <result column="age" property="age"></result>
        <association property="role" javaType="domain.entity.Role">
            <result column="role_name" property="roleName"></result>
            <result column="role_code" property="roleCode"></result>
        </association>
    </resultMap>
    
    private Long id;
    private String userName;
    private String name;
    private Date brithday;
    private Integer age;
    
    private Role role;
    
    联查得到一个用户对应一个角色,一对一
    <select id="selectUserOneToOne" resultMap="resultUser">
            SELECT
    	        user.*,
    	        role.role_code,
    	        role.role_name
            FROM
    	        user
    	        LEFT JOIN user_role ON USER.id = user_role.user_id
    	        LEFT JOIN role ON role.id = user_role.role_id
            WHERE
    	        user.id = 4
    </select>
    
    User{id=4, userName='王4', name='1号', brithday=Tue Jul 13 13:09:46 CST 2021, age=17, role=Role{id=null, roleName='分公司总经理', roleCode='003'}}
    
    • 延迟加载的方式

      fetchType:加载模式,使用lazy,延迟加载

      select:关联的select语句id

      column:查询出来的字段名,同时也作为关联select语句的参数,可以看到在selectUserRoleById里面查出来的字段有id作为查询结果,然后将这个查询结果作为selectRole的参数条件。

  7. 一对多

    ofType:为list里面的类型

    foreignColumn:

    <resultMap id="resultUser" type="domain.entity.User">
        <id column="id" property="id"></id>
        <result column="user_name" property="userName"></result>
        <result column="name" property="name"></result>
        <result column="brithday" property="brithday"></result>
        <result column="age" property="age"></result>
    
        <collection property="roleList" ofType="domain.entity.Role" foreignColumn="id">
            <result column="role_name" property="roleName"></result>
            <result column="role_code" property="roleCode"></result>
        </collection>
    </resultMap>
    
    一个人员拥有多个角色
    [User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=[Role{id=null, roleName='总经理', roleCode='001'}, Role{id=null, roleName='副总经理', roleCode='002'}]}]
    
    • 延迟加载

  8. 多对多

  9. mybatis全局配置文件

    1. 数据库配置文件

      数据库文件 properties文件

      driver=com.mysql.cj.jdbc.Driver
      url=jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC
      username=root
      password=root
      

      在mybatis配置文件XML文件中使用

      <properties resource="db.properties" ></properties>	//引入配置文件<dataSource type="POOLED">    <property name="driver" value="${driver}"/>    <property name="url" value="${url}"/>    <property name="username" value="${username}"/>    <property name="password" value="${password}"/></dataSource>
      
    2. mybatis配置文件

      书写顺序不能乱

      <?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><!--    属性 引入配置文件可使用-->    <properties>        <property name="" value=""/>        <property name="" value=""/>    </properties><!--    设置 -->    <settings>        <setting name="" value=""/>    </settings><!--别名-->    <typeAliases>        <package name=""/>    </typeAliases><!--    类处理器-->    <typeHandlers>        <package name=""/>    </typeHandlers><!--    对象工厂-->    <objectFactory type="">        <property name="" value=""/>    </objectFactory><!--    插件-->    <plugins>        <plugin interceptor=""></plugin>    </plugins><!--    环境 default使用的环境ID-->    <environments default=""><!--        可多个环境-->        <environment id=""><!--            事务管理器-->            <transactionManager type=""></transactionManager>            <dataSource type=""></dataSource>        </environment>    </environments><!--    映射器-->    <mappers>        <package name=""/>        <mapper resource=""></mapper>        <mapper class=""></mapper>        <mapper url="" ></mapper>    </mappers></configuration>
      
      • properties 属性

        <!--<properties resource="db.properties" ></properties> 不用url-->    <properties resource="db.properties">        <!-- 修改db配置文件属性 -->        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>        <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>        <property name="username" value="root"/>        <property name="password" value="root"/>    </properties>
        
      • setting 设置

        MyBatis 中极为重要的调整设置

           <settings><!-- 将lazyLoadingEnabled设置为true表示开启延迟加载,默认为false-->        <setting name="lazyLoadingEnabled" value="true"/><!--将aggressiveLazyLoading设置为false表示按需加载,默认为true-->        <setting name="aggressiveLazyLoading" value="false"/>    </settings>
        
        设置名描述有效值默认值
        cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
        lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
        aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
        multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
        useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
        useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
        autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
        autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
        defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
        defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
        defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
        defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置)未设置 (null)
        safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
        safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
        mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
        localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION | STATEMENTSESSION
        jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
        lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
        defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
        defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
        callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
        returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | falsefalse
        logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
        logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
        proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
        vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
        useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
        configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置
        shrinkWhitespacesInSql从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5)true | falsefalse
        defaultSqlProviderTypeSpecifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.A type alias or fully qualified class nameNot set
      • typeAliases 别名

        <typeAliases>    <typeAlias type="domain.entity.Role" alias="Role1"></typeAlias></typeAliases>
        
        #原:<resultMap id="resultRole" type="domain.entity.Role">        <id column="id" property="id"></id>        <result column="role_name" property="roleName"></result>        <result column="role_code" property="roleCode"></result>    </resultMap>#别名后:<resultMap id="resultRole" type="Role1">    <id column="id" property="id"></id>    <result column="role_name" property="roleName"></result>    <result column="role_code" property="roleCode"></result></resultMap><select id="selectRoleAll" resultMap="resultRole">    select * from role</select>
        

        在Mybatis本身就已经内置了一部分基础类型的别名

        别名映射的类型
        _bytebyte
        _longlong
        _shortshort
        _intint
        _integerint
        _doubledouble
        _floatfloat
        _booleanboolean
        stringString
        byteByte
        longLong
        shortShort
        intInteger
        integerInteger
        doubleDouble
        floatFloat
        booleanBoolean
        dateDate
        decimalBigDecimal
        bigdecimalBigDecimal
        objectObject
        mapMap
        hashmapHashMap
        listList
        arraylistArrayList
        collectionCollection
        iteratorIterator
      • typeHandlers 类处理器

        MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

        类型处理器Java 类型JDBC 类型
        BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
        ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERICBYTE
        ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERICSMALLINT
        IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERICINTEGER
        LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERICBIGINT
        FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERICFLOAT
        DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERICDOUBLE
        BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERICDECIMAL
        StringTypeHandlerjava.lang.StringCHAR, VARCHAR
        ClobReaderTypeHandlerjava.io.Reader-
        ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
        NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
        NClobTypeHandlerjava.lang.StringNCLOB
        BlobInputStreamTypeHandlerjava.io.InputStream-
        ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
        BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
        DateTypeHandlerjava.util.DateTIMESTAMP
        DateOnlyTypeHandlerjava.util.DateDATE
        TimeOnlyTypeHandlerjava.util.DateTIME
        SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
        SqlDateTypeHandlerjava.sql.DateDATE
        SqlTimeTypeHandlerjava.sql.TimeTIME
        ObjectTypeHandlerAnyOTHER 或未指定类型
        EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
        EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERICDOUBLE 类型,用来存储枚举的序数值(而不是名称)。
        SqlxmlTypeHandlerjava.lang.StringSQLXML
        InstantTypeHandlerjava.time.InstantTIMESTAMP
        LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
        LocalDateTypeHandlerjava.time.LocalDateDATE
        LocalTimeTypeHandlerjava.time.LocalTimeTIME
        OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
        OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
        ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
        YearTypeHandlerjava.time.YearINTEGER
        MonthTypeHandlerjava.time.MonthINTEGER
        YearMonthTypeHandlerjava.time.YearMonthVARCHARLONGVARCHAR
        JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE
      • 插件

      • 环境

      • mapper 映射器

        <!-- 使用相对于类路径的资源引用 --><mappers>  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>  <mapper resource="org/mybatis/builder/PostMapper.xml"/></mappers><!-- 使用完全限定资源定位符(URL) --><mappers>  <mapper url="file:///var/mappers/AuthorMapper.xml"/>  <mapper url="file:///var/mappers/BlogMapper.xml"/>  <mapper url="file:///var/mappers/PostMapper.xml"/></mappers><!-- 使用映射器接口实现类的完全限定类名 --><mappers>  <mapper class="org.mybatis.builder.AuthorMapper"/>  <mapper class="org.mybatis.builder.BlogMapper"/>  <mapper class="org.mybatis.builder.PostMapper"/></mappers><!-- 将包内的映射器接口实现全部注册为映射器 -->org.mybatis.builder为包名<mappers>  <package name="org.mybatis.builder"/></mappers>
        
    3. 映射文件

      parameterType:传入参数类型

      resultType:返回参数类型

      resultMap:配置的resultMap标签ID

      属性描述
      id在命名空间中唯一的标识符,可以被用来引用这条语句。
      parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
      parameterMap用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
      resultType期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
      resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
      flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
      useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
      timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
      fetchSize这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
      statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
      resultSetTypeFORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
      databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
      resultOrdered这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false
      resultSets这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。

      对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。(不会)

      <selectKey  keyProperty="id"  resultType="int"  order="BEFORE"  statementType="PREPARED">
      
      属性描述
      keyPropertyselectKey 语句结果应该被设置到的目标属性。如果生成列不止一个,可以用逗号分隔多个属性名称。
      keyColumn返回结果集中生成列属性的列名。如果生成列不止一个,可以用逗号分隔多个属性名称。
      resultType结果的类型。通常 MyBatis 可以推断出来,但是为了更加准确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果生成列不止一个,则可以使用包含期望属性的 Object 或 Map。
      order可以设置为 BEFOREAFTER。如果设置为 BEFORE,那么它首先会生成主键,设置 keyProperty 再执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。
      statementType和前面一样,MyBatis 支持 STATEMENTPREPAREDCALLABLE 类型的映射语句,分别代表 Statement, PreparedStatementCallableStatement 类型。
      
      
    4. mybatis缓存机制

      • 一级缓存

        一级缓存是SqlSession级别的缓存(默认是支持一级缓存,不需要再配置文件中配置一级缓存),在操作数据库时,每个SqlSession类的实例对象中有一个数据结构(HashMap)可以用来存储缓存数据,不同的SqlSession类的实例对象缓存的数据区域(HashMap)是互不影响的。当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据写到内存中,第二次查询不执行sql直接从内存中获取。

        同一个sqlsession的同一个sql语句,第二次执行会直接从内存中获取。

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wpzAf3ya-1630748606469)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis一级缓存.png)]

      • 二级缓存

        二级缓存是Mapper级别的缓存,多个SqlSession类的实例对象操作同一个Mapper配置文件中的sql语句,多个SqlSession类的实例对象可以共用二级缓存,二级缓存是跨SqlSession的。

        一个Mapper有一个自己的二级缓存区域(按照namespace划分),两个Mapper的namespace如果相同,那么这两个Mapper执行的sql查询会被缓存在同一个二级缓存中。

        # 开启二级缓存<settings>    <setting name="cacheEnabled" value="true"/></settings>
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-topieWv0-1630748606470)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis二级缓存.png)]

        二级缓存会存在一个问题就是Mybatis框架不集成第三方缓存系统的话,就会面临分布式储存中脏数据的问题。A、B两台服务器的缓存可能会出现不一致的情况。

        缓存存在自己的主机里,其他主机访问不到,所以数据不一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值