SSM-Mybatis

SSM


MyBatis(ibatis)

一,ORM框架是什么

  • mybtis参考
  • Object Relation Mapping 对象(java对象)关系(数据库表)映射
  • 让操作数据库关系表,就像操作对象一样

二,MyBatis 是什么

  • 它是一款半自动的ORM持久层框架,具有较高的SQL灵活性
  • 区别于全自动ORM hibernate 它需要手动编写SQL
  • 实现Java工程与数据库一定程度上的分离,简化JDBC
  • MyBatis 本是apache 开源项目 iBatis ,2010 从 Apache software foundation 迁到 Google code 更名 MyBatis 2013年 迁移到 GitHub

三,需要那些知识储备

  1. JDBC
  2. MySQL
  3. Java基础
  4. Maven
  5. Junit

四,学习要点

  • MyBatis 使用环境搭建
  • 使用映射配置实现CURD
  • 动态SQL SQL语句构建
  • 多表查询
  • 日志
  • MyBatis 缓存机制

五,如何配置MyBatis环境

  1. 官方网站

  2. 使用步骤

    1. 下载mybatis相关的jar,在上面的中文网站也是可以下载的 下载地址

      1. mybatismybatis-3.5.2.zip

        1. mybatis
        2. 它所依赖的jar
      2. JDBC驱动mysql-connector-java-8.0.11.zip

      3. mybatis 源码 mybatis-3-mybatis-3.5.2.zip

      4. maven

        	<!--junit test-->
            <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.11</version>
              <scope>test</scope>
            </dependency>
        
            <!--    mybatis-->
            <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.4.5</version>
            </dependency>
        
            <!--    mysql driver-->
            <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.23</version>
            </dependency>
        
            <!--    日志-->
            <dependency>
              <groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.17</version>
            </dependency>
        
    2. 编写导入配置文件 并测试环境

      1. mybatis主配置文件(mybatis-config.xml)

        1. <?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文件 -->
            <properties resource="database.properties" />
              
            <!--配置log4j-->
            <settings>
            	<setting name="logImpl" value="LOG4J" />
            </settings>
              
            <environments default="development">
              <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                  <property name="driver" value="${driver}"/>
                  <property name="url" value="${jdbc.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. 部分情况下${url} 应该写成 ${jdbc.url} 否则url 会不识别(换个名字也可以)

        3. xml中& 不识别需要转义 &amp;

        4. database.properties

        5. driver=com.mysql.jdbc.Driver
          jdbc.url=jdbc:mysql://127.0.0.1:3306/stu_new_manager?useUnicode=true&amp;characterEncoding=utf-8
          username=root
          password=123456	
          
        6. log4j.properties

      2. ### 设置Logger输出级别和输出目的地 
        ### debug更详细,如果设为info那么打印出的表数据遇到字符串就不显示,此外还有logfile
        log4j.rootLogger=debug,stdout
        ### 把日志信息输出到控制台 ### 
        log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
        #log4j.appender.stdout.Target=System.err 
        log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout 
         
        ### 把日志信息输出到文件:jbit.log ### 
        #log4j.appender.logfile=org.apache.log4j.FileAppender 
        #log4j.appender.logfile.File=jbit.log 
        #log4j.appender.logfile.layout=org.apache.log4j.PatternLayout 
        #log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n 
         
        ###显示SQL语句部分 
        #log4j.logger.com.mybatis=DEBUG
        #log4j.logger.com.mybatis.common.jdbc.SimpleDataSource=DEBUG 
        #log4j.logger.com.mybatis.common.jdbc.ScriptRunner=DEBUG 
        #log4j.logger.com.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG 
        #log4j.logger.java.sql.Connection=DEBUG
        #log4j.logger.java.sql.Statement=DEBUG
        #log4j.logger.java.sql.PreparedStatement=DEBUG
        
    3. 创建数据库表

    4. 创建实体类最好与数据库字段一致

    5. 创建接口CRUD方法

      package com.itCast.dao;
      
      import com.itCast.domain.User;
      
      import java.util.List;
      
      public interface UserMapper {
          List<User> getUserList();
      }
      
      
    6. 创建接口实现类

      1. 原来的方式 :

        1. com.itCast.dao.impl.UserDaoImpl 实现类
        2. com.itCast.dao.UserDao interface
      2. mybatis的方式

        com.itCast.dao.UserMapper.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">
        <!--namespace 接口全类名 id 接口方法名 resultType 返回值类型-->
        <mapper namespace="com.itCast.dao.UserMapper">
            <select id="getUserList" resultType="com.itCast.domain.User">
                select * from user;
             </select>
        </mapper>
        

六,MyBatis 学习要点展开

一,基础配置使用
  1. 当参数过多可以使用Map 集合比较灵活
    1. key-value 在sql中取出key #{u_name}
    2. 多个参数Map
    3. 对象的参数是固定的不能改变
  2. 模糊查询
    1. 在java的代码中 select * from user where name like #{u_name}; name="%value%"
    2. 在sql 中写死 select * from user where id like "%"#{u_name}"%";
  3. 配置解析
    1. environments

      配置不同的连接数据库的配置

    2. properties

      配置外部属性 database.properties

    3. 标签顺序很重要

    4. 别名

      1. xml

        1. typeAlias
        2. package
            <typeAliases>
        <!--        <typeAlias type="com.itCast.domain.User" alias="user"/>-->
                <package name="com.itCast.domain"/>
            </typeAliases>
        
      2. 注解 xml : package

        1. 可以通过注解自定义名字 @Alias("user01")
    5. 映射

      1. 方式一

         <mappers>
             <mapper resource="com/itCast/dao/UserMapper.xml"/>
         </mappers>
        
      2. 方式二

          <mappers>
                <mapper class="com.itCast.dao.UserMapper"/>
            </mappers>
        
        • 方式二的注意点
          • 接口名字必须和xml名字一致
          • 并且接口和xml映射必须在同包之下
      3. 方式三

        <package name="com.itCast.domain"/>
        
        • 要求和方式二一致
    6. 如何解决字段名和类属性不一致

      1. 修改Sql

      2. resultMap

        <?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.itCast.dao.UserMapper">
        <!-- resultMap=id  -->
            <resultMap id="userMap" type="user">
        <!--  column: 列 数据库  property 属性 类属性   -->
                <result column="id" property="uId"/>
                <result column="u_name" property="uName"/>
                <result column="u_pass" property="uPass"/>
            </resultMap>
        
        <!--    按照ID查询-->
            <select id="findUserById" resultMap="userMap" parameterType="int">
                select * from user where id = #{id};
            </select>
        </mapper>
        
        1. 字段一致不需要写 <result column="id" property="uId"/>
  4. 日志
    1. 常用的 LOG4J

    2. 配置文件来灵活配置日志输出

    3. LOG4J使用

      1. 导入依赖

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
      2. 加入log4j.properties

        #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
        log4j.rootLogger=DEBUG,console,file
        
        #控制台输出的相关设置
        log4j.appender.console = org.apache.log4j.ConsoleAppender
        log4j.appender.console.Target = System.out
        log4j.appender.console.Threshold=DEBUG
        log4j.appender.console.layout = org.apache.log4j.PatternLayout
        log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
        
        #文件输出的相关设置
        log4j.appender.file = org.apache.log4j.RollingFileAppender
        log4j.appender.file.File=./log/kexing.log
        log4j.appender.file.MaxFileSize=10mb
        log4j.appender.file.Threshold=DEBUG
        log4j.appender.file.layout=org.apache.log4j.PatternLayout
        log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
        
        #日志输出级别
        log4j.logger.org.mybatis=DEBUG
        log4j.logger.java.sql=DEBUG
        log4j.logger.java.sql.Statement=DEBUG
        log4j.logger.java.sql.ResultSet=DEBUG
        log4j.logger.java.sql.PreparedStatement=DEBUG
        
      3. private static Logger logger =Logger.getLogger(MapperTest.class);
        
        logger.info("info:信息");
                SqlSession session = mybatisUtils.getSqlSession();
                UserMapper mapper = session.getMapper(UserMapper.class);
                List<User> users = mapper.findUserById(1);
                for (User user : users) {
                    logger.debug(user);
                }
                logger.error("error");
        
  5. 分页查询
    1. xml

      <!--    分页查询-->
          <select id="findUserLimit" parameterType="map" resultMap="userMap">
              select * from user limit #{startIndex},#{pageSize};
          </select>
      
    2. test

         @Test
          public void findUserLimitTest(){
              SqlSession session = mybatisUtils.getSqlSession();
              UserMapper mapper = session.getMapper(UserMapper.class);
      
              Map<String, Integer> map = new HashMap<>();
              map.put("startIndex",1);
              map.put("pageSize",4);
      
              List<User> users = mapper.findUserLimit(map);
              for (User user : users) {
                  System.out.println(user);
              }
              session.close();
          }
      
  6. 注解
    • 注意 ${} #{} 获取值的方式第二种更安全,前者容易sql注入
  7. lombok 简化Javabean的书写
    1. idea 下载 plugins

    2. maven 坐标

    3. 注解使用

      @ToString
      @AllArgsConstructor
      @NoArgsConstructor
      @EqualsAndHashCode
      @Getter
      @Setter
      @Data
      
三,多表关系和动态SQL
  1. 动态SQL

    • 接口 List<User> findUserByCondition(User user);

    • XML

      <!--    条件查询-->
          <select id="findUserByCondition" parameterType="user" resultMap="userMap">
              select * from user
              <where>
                  <if test="uId!=0" >
                      and id = #{uId}
                  </if>
                  <if test="uName!=null">
                      and u_name = #{uName}
                  </if>
                  <if test="uPass!=null">
                      and u_pass = #{uPass}
                  </if>
              </where>
          </select>
      
      <!--    根据集合查询-->
          <select id="findUserByIds" parameterType="list" resultMap="userMap">
              <include refid="findUser"/>
              <where>
                  <foreach collection="list" open="id in (" close=")" separator="," item="id">
                      #{id}
                  </foreach>
              </where>
          </select>
      
      <!--    sql 抽取-->
          <sql id="findUser">
              select * from user
          </sql>
      
    • 测试

      //条件查询
          @Test
          public void findUserByConditionTest(){
              SqlSession session = mybatisUtils.getSqlSession();
              UserMapper mapper = session.getMapper(UserMapper.class);
              List<User> user = mapper.findUserByCondition(new User(1, "user1", "user1"));
              for (User user1 : user) {
                  System.out.println(user1);
              }
              session.close();
      
  2. 多表查询

    1. 一对多

      1. sql 语句

        select u.id uid,u.u_name uname,a.id aid,a.money amoney from user u,account a where u.id = a.u_id;
        
      2. map

            <resultMap id="userAccount" type="java.util.Map">
                <result property="aid" column="aid"/>
                <result property="uname" column="uname"/>
                <result property="amoney" column="amoney"/>
            </resultMap>
        
        List<HashMap<Object,Object>> findUserAccount();
        
    2. 多对一

      1. sql

        select
               u.id uid,u.u_name uname,a.id aid,a.money amoney
        from
            user u  left join account a
        on
              u.id = a.u_id;
        
      2. 结果集

            <resultMap id="AccountUser" type="userA">
                <id property="id" column="uid"/>
                <result property="u_name" column="uname"/>
        <!--        javaTyp指定类型 ofType 集合泛型
            private int id;
            private int u_id;
            private int money;
         -->
                <collection property="account" ofType="account">
                    <id property="id" column="aid"/>
                    <result property="money" column="amoney"/>
                </collection>
            </resultMap>
        
四,核心配置文件
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUAvrhJQ-1636367705235)(D:\ycdl\JavaNote\笔记\img\mybatis1.jpg)]

  • 自定义类型转换器

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibxb205o-1636367705238)(C:\Users\2775371841\AppData\Roaming\Typora\typora-user-images\image-20210415163845457.png)]

  • 代码

    public class DateTypeHandler extends BaseTypeHandler<Date> {
        //java 类型转换成数据库需要的类型
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
            long time = parameter.getTime();
            ps.setLong(i,time);
        }
    
        //数据库类型转换成java需要的类型
        @Override
        public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
            long rsLong = rs.getLong(columnName);
            Date date = new Date(rsLong);
            return date;
        }
    
        //数据库类型转换成java需要的类型
        @Override
        public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            long rsLong = rs.getLong(columnIndex);
            Date date = new Date(rsLong);
            return date;
        }
    
        //数据库类型转换成java需要的类型
        @Override
        public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            long rsLong = cs.getLong(columnIndex);
            Date date = new Date(rsLong);
            return date;
        }
    }
    
     <typeHandlers>
            <typeHandler handler="com.utils.DateTypeHandler"/>
        </typeHandlers>
    
  • plugains

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LiRj7yM2-1636367705239)(D:\ycdl\JavaNote\笔记\img\mybatis3.jpg)]

    • 导入依赖

    •     <dependency>
              <groupId>com.github.pagehelper</groupId>
              <artifactId>pagehelper</artifactId>
              <version>4.1.6</version>
          </dependency>
      
                  <!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
          <dependency>
              <groupId>com.github.jsqlparser</groupId>
              <artifactId>jsqlparser</artifactId>
              <version>1.4</version>
          </dependency>
    
  • 在主配置文件上配置

    • <plugins>
              <plugin interceptor="com.github.pagehelper.PageHelper">
                  <!-- 属性是数据库不同语言不同-->
                  <property name="dialect" value="mysql"/>
              </plugin>
          </plugins>
      
  • test

    • //第二种方式
         @Test
         public void getUserListTest2(){
             SqlSession session = mybatisUtils.getSqlSession();
      //        System.out.println(session);
              UserMapper mapper = session.getMapper(UserMapper.class);
      
              PageHelper.startPage(1,3);
      
              List<User> list = mapper.getUserList();
              for (User user : list) {
                  System.out.println(user);
              }
          }
      
      
    
    
  • 特别注意

    • sql不能加 ;
    • 在查询所有时才管用
五, 延迟加载概念,和怎么配置延迟加载,以及他的原理
  • 延迟加载的概念

mybatis的延迟加载就是按需查询,在需要的时候进行查询 (分步查询,按需查询)

当然 Hibernate也是支持的

这样做可以完成功能,但是我们只是需要显示图书类型,点击的时候才显示该类型的图书,如果能做到开始只查询类型,点击类型的时候再查询该类型的图书,就不需要进行两表联查了,可以提高查询的效率,也比较节省内存,这就是延迟加载。

  • 哪些方面支持

mybatis仅仅支持association(一对一) collection(一对多) 的延迟加载

  • 如何设置使用
<mapper namespace="cn.xh.dao.UserDao">
    <select id="findCategoryWithLazingload" resultMap="categoryMap">
        select * from category
    </select>
    <resultMap id="categoryMap" type="cn.xh.pojo.Category">
        <id column="cid" property="cid"></id>
        <result column="cname" property="cname"></result>

        <collection property="books" column="cid" select="findBookWithLazy"></collection>
    </resultMap>

    <select id="findBookWithLazy" parameterType="int" resultType="cn.xh.pojo.Book">
        select * from book where cid = #{cid}
    </select>
</mapper>

<settings>
    <!--启动延迟加载  默认为false-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--按需加载,默认为true-->
    <setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
六,缓存
  1. 什么是缓存

    • 存在内存中的临时数据
    • 将用户经常查的数据放进缓存,降低访问数据库的次数,提高性能
  2. mybatis 缓存

    • 方便的定制和配置缓存

    • 定于了两级缓存

      • 默认开启一级缓存,SqlSession 级别(本地缓存)

        • 一次会话 ,close() 后关闭

        • 一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方
          法时,就会清空一级缓存。防止后续查询发生脏读(脏读:查询到过期的数据)

        • 特别注意 一个mapper中sqlid是方法全路径 ,所以同一个mapper不能共享需要二级缓存

        • Mybatis内部存储缓存使用一个HashMap缓存数据,key为hashCode+sqlId+Sql语句。value为从查询
          出来映射生成的java对象。
          一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一
          级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除(禁用
          一级缓存)。

      • 二级缓存需要手动开启 多个sqlsession(相同的namespace)

        • 通过 Cache 接口来定义二级缓存
    • 原则

      • 最近最少使用
      • 先进先出
  3. 一级缓存和二级缓存

    1. 一级缓存失效

      1. select 语句执行结果会被缓存
      2. 数据库写入时缓存失效
      3. 最近最少使用算法
      4. 不定时刷新缓存
      5. 调用的对象不共享可以安全的被修改,互相不受影响
    2. 二级缓存

      1. 开启

        • 在主配置文件中写入

          • <setting name="cacheEnabled" value="true" />
            
        • 在Mapper.xml文件中开启

          • <cache/>

          • <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
            
      2. 生效

        1. 在Mapper.xml全局生效
        2. 在关闭会话时一级缓存会保存在二级缓存
        3. Mapper.xml 的数据会保存在自己当中
      3. 顺序

        1. 先看二级缓存
        2. 再看一级缓存
        3. 然后找不到,看数据库
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值