• mybatis学习笔记


    简介

    1、持久层框架
    2、maven仓库获取
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    

    构建mybatis项目

    1、编写mybatis 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>
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <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="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
    </configuration>
    

    2、编写mybatis工具类

    public class MybatisUtils {
    
        private static SqlSessionFactory sqlSessionFactory;
    
        static {
            InputStream inputStream = null;
            try {
                String resource = "mybatis-config.xml";
                inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        public static SqlSession getSqlSession(){
            return  sqlSessionFactory.openSession();
        }
    }
    

    3、编写dao层接口

    public interface UserMapper {
        public List<User> getUserList();
    }
    

    4、编写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="com.tang.dao.UserMapper">
        <select id="getUserList" resultType="com.tang.pojo.User">
        select * from user
      </select>
    </mapper>
    

    5、测试类

    public class UserDaoTest {
    
    @Test
    public void test(){
        SqlSession sqlSession =null;
        try {
            sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            sqlSession.close();
        }
    }
    

    }

    maven资源过滤

     <!-- 资源过滤-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    

    CRUD操作

    parameterType:参数类型
    resultType:返回类型

    查询用户通过id:

    <select id="getUserById" parameterType="int" resultType="com.tang.pojo.User"> select * from user where id=#{id} </select>

    增加用户

    注意:增删改需要提交事务
    <insert id="addUser" parameterType="com.tang.pojo.User"> insert into user(id,name,pwd) values(#{id},#{name},#{pwd}) </insert>

        public void addUser(){
        SqlSession sqlSession =null;
        try {
            sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.addUser(new User(9,"hahha","123"));
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            sqlSession.close();
        }
    	}
    

    配置解析

    configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
    environment(环境变量)
    transactionManager(事务管理器)
    dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)
    

    1、environments(环境配置)

    <environments default="development">
      	<environment id="development">
        <transactionManager type="JDBC">
          <property name="..." value="..."/>
        </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、在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")
    2、有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
    3、MyBatis默认使用事务管理器JDBC 连接池POOLED
    

    2、properties(属性)

    创建db.properties文件

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username=root
    password=root
    

    在mybatis-config.xml中引入properties文件

    <configuration>
    <properties resource="db.properties"/>
    ....
    </configuration>
    当两个文件同一字段,优先使用外部配置文件。
    

    3、类型别名(typeAliases)

    <typeAliases>
      <typeAlias alias="Author" type="domain.blog.Author"/>
      ....
    </typeAliases>
    
    也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
    <typeAliases>
      <package name="domain.blog"/>
    </typeAliases>
    
    在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值
    @Alias("author")
    public class Author {
        ...
    }
    

    4、设置(settings)

    设置名	描述	有效值
    cacheEnabled	全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。	true | false	true
    lazyLoadingEnabled	延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。	true | false
    logImpl	指定 MyBatis 所用日志的具体实现,未指定时将自动查找。	SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING	未设
    

    5、映射器(mappers)

    <!-- 使用相对于类路径的资源引用 -->
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
    </mappers>
    
    
    <!-- 使用映射器接口实现类的完全限定类名 -->
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
    </mappers>
    注意:1、使用此方法,接口必须和他的mapper配置文件名相同
    	 2、接口和他的mapper配置文件必须在同一包下
    
    
    <!-- 将包内的映射器接口实现全部注册为映射器 -->
    <mappers>
      <package name="org.mybatis.builder"/>
    </mappers>
    注意:1、使用此方法,接口必须和他的mapper配置文件名相同
    	 2、接口和他的mapper配置文件必须在同一包下
    
    ### 6、作用域(Scope)和生命周期 ###
    SqlSessionFactoryBuilder:这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
    SqlSessionFactory:SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
    SqlSession:SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。
    

    结果映射resultMap

    resultMap 元素是 MyBatis 中最重要最强大的元素。




    然后在引用它的语句中设置 resultMap 属性就行了
    <select id="selectUsers" resultMap="userResultMap">
      select user_id, user_name, hashed_password
      from some_table
      where id = #{id}
    </select>
    

    日志

    作用:出现异常排错
    以前:sout debug
    
    SLF4J 
    LOG4J 【掌握】
    LOG4J2  
    JDK_LOGGING 
    COMMONS_LOGGING 
    STDOUT_LOGGING 【掌握】
    NO_LOGGING
    
    标准日志STDOUT_LOGGING 输出
    <settings>
      <setting name="logImpl" value="STDOUT_LOGGING "/>
    </settings>
    

    LOG4J

    1、导包
    2、创建log4j.properties配置文件
    设置
    log4j.rootLogger = debug,stdout,D,E
     
     输出信息到控制抬 
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
     
    输出DEBUG 级别以上的日志到=E://logs/error.log
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = E://logs/log.log
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = DEBUG 
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
     
    输出ERROR 级别以上的日志到=E://logs/error.log
    log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.E.File =E://logs/error.log 
    log4j.appender.E.Append = true
    log4j.appender.E.Threshold = ERROR 
    log4j.appender.E.layout = org.apache.log4j.PatternLayout
    log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    

    使用注解开发

    @Param()
    基本类型的参数需要加上
    引用类型不用加
    我们在sql中的引用就是@Param()中设定的属性名
    

    多对一查询

    按照查询嵌套处理

    <!--思路:
    1、查询所有学生的信息
    2、根据查询出来学生信息的tid,寻找对应的老师-->
    <select id="getStudent" resultType="StudentTeacher">
        select * from student
    </select>
    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id=#{id}
    </select>
    
    </mapper>
    

    按照结果嵌套处理

    <!--    按照结果嵌套处理-->
    <select id="getStudent2" resultType="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid = t.id
    </select>
    
    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher"  javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    

    一对多查询

    例如:一个老师有多个学生

    按照结果嵌套查询

     <!--    按照结果嵌套处理-->
    <select id="getTeacher" resultType="StudentTeacher">
    select s.id sid,s.name sname,t.name tname,t.id tid
    from student s,teacher t
    where s.tid = t.id
    </select>
    
    <resultMap id="StudentTeacher" type="teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
    <!--  复杂的属性,我们需要单独处理 对象association  集合:collection
    javaType指定属性的类型
    ofType指定集合中,泛型的类型-->
        <collection property="Students"  ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    

    按照查询嵌套处理

    <!--    按照查询嵌套处理-->
    <select id="getTeacher" resultType="StudentTeacher2">
    select * from teacher where id = #{tid}
    </select>
    
    <resultMap id="StudentTeacher2" type="Teacher">
        <collection property="Students"  column="id" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId"/>
    </resultMap>
    
    <select id="getStudentByTeacherId" resultType="Student">
        select * from student where tid=#{tid}
    </select>
    

    小结:
    1、关联 多对一 association
    2、集合 一对多 collection
    3、javaType & ofType
    javatype:指定实体类属性类型
    ofType:指定映射到list或者集合中的泛型类型

    动态sql

    if

    这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有处于 “ACTIVE” 状态的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果
    <select id="findActiveBlogWithTitleLike"
      resultType="Blog">
      SELECT * FROM BLOG
      WHERE state = ‘ACTIVE’
      <if test="title != null">
    	AND title like #{title}
      </if>
    </select>
    

    choose、when、otherwise

    有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
    <select id="findActiveBlogLike"
     resultType="Blog">
      SELECT * FROM BLOG WHERE state = ‘ACTIVE’
      <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
      </choose>
    </select>
    

    where

    where 元素只会在子元素有返回内容的情况下才插入 “WHERE” 子句。
    若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
    <select id="findActiveBlogLike"
     resultType="Blog">
      SELECT * FROM BLOG
      <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
      </where>
    </select>
    

    set

    set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号
    <update id="updateAuthorIfNecessary">
      update Author
        <set>
          <if test="username != null">username=#{username},</if>
          <if test="password != null">password=#{password},</if>
          <if test="email != null">email=#{email},</if>
          <if test="bio != null">bio=#{bio}</if>
        </set>
      where id=#{id}
    </update>
    

    和 where 元素等价的自定义 trim 元素为:

    ...

    与 set 元素等价的自定义 trim 元素:

    ...

    foreach

    动态 SQL 的另一个常见使用场景是对集合进行遍历

    它允许你指定一个集合(list)
    index 是当前迭代的序号
    item 的值是本次迭代获取到的元素
    

    缓存

    默认情况下,只启用了本地的会话缓存(一级缓存),它仅仅对一个会话中的数据进行缓存。
    要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
    基本上就是这样。这个简单语句的效果如下:

    映射语句文件中的所有 select 语句的结果将会被缓存。
    映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
    缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
    缓存不会定时进行刷新(也就是说,没有刷新间隔)。
    

    二级缓存

    1、开启默认缓存(一般默认开启,单独写出来,起提示作用)



    2、在当前mapper.xml中,添加标签

    小结:
    1、只要开启了二级缓存,在同一个mapper下生效,二级缓存只能针对一个namespace有效。。
    2、所有数据先放入一级缓存中,当一级缓存关闭或提交时,自动放入二级缓存。
    

    原理

    第一次查询先看二级缓存里面有没有,在看一级缓存里面,没有就查询。

    资料来源:B站秦疆老师(遇见狂神说)
    https://space.bilibili.com/95256449

  • 相关阅读:
    JVM学习五:JVM之类加载器之编译常量和主动使用
    JVM学习一:JVM之类加载器概况
    JVM学习三:JVM之类加载器之连接分析
    JVM学习二:JVM之类加载器之加载分析
    JVM学习四:JVM之类加载器之初始化分析
    高斯滤波详解 附python和matlab高斯滤波代码
    图像最大池化
    图像平均池化 pytorch库中的平均池化
    图像色彩量化处理
    图像RGB到HSV色彩空间转换及其逆变换
  • 原文地址:https://www.cnblogs.com/xiaolaodi1999/p/13463284.html
Copyright © 2020-2023  润新知