三天学完Mybatis

MyBatis第一天】

一、 主要内容

1. MyBatis的简介

2. MyBatis的环境搭建

3. MyBatis的框架详解

4. MyBatis中的优化处理

二、 学习目标

节数

知识点

要求

第一节(MyBatis的简介

如何理解框架

 

MyBatis框架的简介

 

第二节(MyBatis的环境搭建

搭建MyBatis环境的步骤

 

MyBatis环境搭建的意义

 

第三节(MyBatis环境搭建详解)

搭建环境内容具体意义

 

第四节(MyBatis框架搭建优化

其他搭建优化操作

 

 

第一节 MyBatis中的简介

[1]为什么使用MyBatis

  目前使用开发遇到的问题

        A、每一个操作对应的使用Dao中的方法,每一个方法中都需要连接数据库,这样我们连接数据库的代码就需要写好多次

        B、如果我们做的是查询的操作,从rs中取值是一个比较麻烦,而且影响开发效率的问题

解决方案:

        (1)提取DBUtil工具类即可

            优点:不用在每一次书写连接数据库的操作

            缺点:传统的JDBC连接数据库的效率非常慢

         (2)使用数据库连接池连接数据库

             优点:连接数据库的速度比较快

             缺点:没有办法实现SQL语句和java代码之间的解耦 

        (3)使用MyBatis框架

              作用:[1]解决了SQL语句和java代码之间的耦合

                     [2]连接数据库的效率也比较快

                     [3]取值问题就会变得非常的简单  

[2]什么是框架?

       框架就是使用别人封装好的代码即可 --框架体现的形式(jar包)

 Jar   API   源码)

[3]什么是MyBatis框架

   MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github

     MyBatis是一个半自动的ORM框架

     ORM: Object Relational Mapping   (作用解决数据库发展和面向对象发展不一致的问题)

                O:面向对象

                R:关系型数据库

                M:映射

     半自动:myBatis框架是需要我们自己手写sql语句

    MyBatis框架不依赖于服务器

 

第二节  MyBatis框架的搭建

01第一步  导包   

mysql驱动包+mybatis的核心包+mybatis的依赖

 

02 书写配置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="mysql">

         <!--MySQL数据库连接-->
         <environment id="mysql">
             <!--MyBatis中的事务管理  目前的事务管理和JDBC中的事务保持一致-->
             <transactionManager type="JDBC"></transactionManager>
             <!--底层使用连接池连接数据库-->
             <dataSource type="POOLED">

                 <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis2?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"></property>
                 <property name="username" value="root"></property>
                 <property name="password" value="root"></property>

             </dataSource>
         </environment>

         <!--ORCL数据库-->
        <!-- <environment id="orcl">
             <transactionManager type=""></transactionManager>
             <dataSource type=""></dataSource>
         </environment>-->

     </environments>
    <!--进行mapper文件的扫描-->
    <mappers>
        <!--resource:书写的是XML所在的目录-->
        <mapper resource="com/bjsxt/mapper/FlowerMapper.xml"></mapper>

    </mappers>

</configuration>

 

 

03 第三步  配置FlowerMapper.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="a.b">

    <!--
        List<Flower>  selectAll();

       id:方法名称

       resultType:返回值类型

            查询返回的时候一般不是对象就是集合

            如果返回值是一个对象,就写对象所在包的全路径

            如果返回值是一个集合,这个时候书写集合的泛型
    -->

     <select id="selectAll" resultType="com.bjsxt.entity.Flower">

          SELECT   *  from   flower

     </select>

</mapper>

 

04书写测试代码

 

public static void main(String[] args) throws IOException {

    //[A]解析MyBatis.xml
    InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
    //[B]获得session工厂
    SqlSessionFactory  factory=new SqlSessionFactoryBuilder().build(inputStream);
    //[C]获得session对象
    SqlSession sqlSession = factory.openSession();
    //[D]调用方法
    List<Flower> list = sqlSession.selectList("a.b.selectAll");
    System.out.println(list);
    //[E]关闭sqlsession
    sqlSession.close();
}

 

优点:

A、连接数据库速度快

B、实现了SQL语句和JAVA代码之间的解耦

C、数据库查询取值非常的方便

 

第三节  MyBatis框架搭建详解

01 Jar包目录介绍

 

可以用ant编译Java类,生成class文件ant可以把相关层架构成包 

java文件解析包.spring依赖这个包

动态代理包.mybatis不需编写实现类

日志包.spring依赖这个包

字节码解析助手,处理.class文件

日志包

mybatis核心包

数据库驱动

日志

 

 

02配置详解 

2.全局配置文件mybatis.xml

2.1 <environments default="demo">

2.1.1 default配置当前所使用的环境.值必须是<environment>的id值

2.1.2 可以有多个<environment>标签.

2.2 <environment> 声明可能使用的环境,会被< environments>引用

2.3 <transactionManager type="JDBC">

2.3.1 事务管理器类型.

2.3.2 type属性可取值:

2.3.2.1 JDBC 底层事务与JDBC原有事务管理相同

2.3.2.2 MANAGED  MyBatis不去管理事务,交给其他容器进行管理.

2.4 <dataSource type="POOLED">

2.4.1 POOLED : 使用连接池技术. 访问频率比较高时使用.连接池的使用可以降低服务器压力,提高连接对象重用性

2.4.2 UNPOOLED: 不使用连接池技术.每次对数据库访问时打开数据库连接,访问结束后关闭数据库连接.

2.4.3 JNDI : java命名目录接口.数据库的连接可以依赖于其他技术或应用.

2.5 <mapper> 常用属性

2.5.1 resource="com/bjsxt/xxx.xml" 加载项目中资源,目录寻找,中间是/

2.5.2 url="" 加载互联网或本机的配置文件.示例如下:

       <mapper url="file:///E:/FlowerMapper.xml"/>

 

03 mapper.xml 中标签解释

3.1 <mapper >中namespace=""值相当于接口名

3.2 id 属性: 相当于方法名

3.3 resultType属性:返回值类型,如果返回值是集合,写集合的泛型.

3.4 parameterType属性:参数类型.如果没有参数省略该属性.

<select id="selAll" resultType="com.bjsxt.pojo.Flower" parameterType="">

       select * from flower

</select> 

 

04引入本地DTD文件

 

第一步 下载对应的DTD

   直接在网络下载即可

 

第二步 找到Setting文件

 

 

第三步 找到DTD

 

第四步 引入本地DTD文件

 

第四节 MyBatis框架搭建优化

01配置别名 

<typeAliases> 

     <!--单独的给某一个文件起别名  --> 

      <typeAlias type="com.bjsxt.pojo.Flower" alias="a"/> 

<!--给整个包下面的文件起别名   这时候别名的名称就是类的名称 不区分大小写--> 

      <package name="com.bjsxt.pojo"/> 

 </typeAliases> 

 

02配置Mapper(本地文件)

<mapper url="file:///E:/FlowerMapper.xml"/> 

03属性的名称配置

<properties resource="jdbc.properties"></properties> 

引入properties配置文件 

A、需要明白MyBatis也是支持属性文件的读取的

B、可以让代码的结构更加的清晰

 

 

 

04配置settings开启log4j支持

4.1日志的作用:

A、记录错误的信息到文件中

B、有日志级别方便查看

4.2 Log4J的五种级别:

    4.1 FATAL 严重错误

4.2 ERROR 错误

    4.3 WARN 警告

    4.4 INFO 普通信息

    4.5DEBUG调试信息

4.3 DEBUG 调试信息

<settings> 

     <setting name="logImpl" value="LOG4J"/> 

</settings> 

 

4.4日志文件

log4j.rootCategory=error, CONSOLE,LOGFILE 

#必须知道com.bjsxt.mapper:是namespace含义是只要是用com.bjsxt.,mapper开始的命名空间日志的级别都是debug模式,不是包名 

log4j.logger.com.bjsxt.mapper=debug 

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 

log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n 

# LOGFILE is set to be a File appender using a PatternLayout. 

log4j.appender.LOGFILE=org.apache.log4j.FileAppender 

log4j.appender.LOGFILE.File=d:/axis.log 

log4j.appender.LOGFILE.Append=true 

log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout 

log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n 

4.5导入步骤

[1]导入属性文件

[2]在mybatis.xml中配置日志的操作

[3]修改需要打印的日志信息

 

MyBatis第二天

一、 主要内容

1. MyBatis中的三种查询方式

2. MyBatis中的三种参数传递

3. MyBatis中增删改操作

4. MyBatis中Mapper代理方式

5. MyBatis中多参传递

6. MyBatis中SQL语句动态拼接

二、 学习目标

节数

知识点

要求

第一节(MyBatis中三种查询方式

MyBatis中查询方式A

掌握

MyBatis中查询方式B

掌握

第二节(MyBatis中三种参数传递)

MyBatis中三种参数传递

掌握

第三节 (MyBatis中增删改操作)

MyBatis中增删改

掌握

第四节 (MyBatis中Mapper代理)

MyBatis中Mapper代理意义

掌握

第五节 (MyBatis中多参数传递)

MyBatis中多参数传递方式

掌握

 

第六节 (MyBatis中SQL语句动态拼接)

MyBatis中SQL动态拼接标签A

掌握

MyBatis中SQL动态拼接标签B

掌握

MyBatis中SQL动态拼接标签C

掌握

 

第一节 MyBatis中三种查询方式

01 Mapper文件代码

<mapper namespace="com.bjsxt.mapper.FlowerMapper">      
    <select id="selectAll" resultType="flower">           
        select *  from   flower         
    </select>          
    <select id="selectOne" resultType="flower">    
        select *  from flower  where  id=1   
    </select> 

        //Spring已经把一些常见的类型起了别名,Map对应别名是map.所以不需写全路径      
    <select id="selectMore" resultType="map">     
        select  *  from  flower           
    </select>      
</mapper>

 

02 测试文件

 

   public static void main(String[] args) throws IOException {
        //[1]解析mybatis.xml        
        InputStream is = Resources.getResourceAsStream("myBatis.xml");                        
        // [2]获得session工厂        
        SqlSessionFactory  factory=new SqlSessionFactoryBuilder().build(is);
        //[3]获得session对象       
         SqlSession session = factory.openSession();                        
        // [4]执行查询操作                        
        // √【A】查询方式一 使用于查询多条数据的时候          
         List<Flower> list = session.selectList("com.bjsxt.mapper.FlowerMapper.selectAll");                  
        // √【B】查询方式二   适用场景:查询最多是条数据的时候       
          Flower fl = session.selectOne("com.bjsxt.mapper.FlowerMapper.selectOne");                  
        // 【C】查询方式三  selectMap("执行的方法","希望数据库的哪一列作为key")         
        // 适用的场景 :查询的时候可以快速的通过某一列确定对应的数据          
        Map<Object, Object> map = session.selectMap("com.bjsxt.mapper.FlowerMapper.selectMore", "id");   
              Object fl = map.get(2);          
         System.out.println(fl);                  
        // [5]关闭session          
         session.close();                        }
    }
}

总结:即根据查询想要的结果选择三种方法的调用

 

第二节 MyBatis中三种参数传递

01Mapper层代码

 

<!--方式一   public Flower  selectOne2(Integer  id) -->   
<select id="selectOne2" resultType="flower" parameterType="int">  
    select  *  from  flower  where  id=#{param1}          
</select>          
<!--方式二   public   Flower  selectOne3(Flower fl);  -->

//即把参数类型定为flower,因为它本身就有多个属性 
<select id="selectOne3" resultType="flower" parameterType="flower">  
<!--id=#{对象中的属性名}  -->要与flower中的属性保持一致       
select  *  from  flower  where  id=#{id}  and  name=#{name}  
</select>
<!--方式三   public   Flower  selectOne3(Flower fl);  -->    
<select id="selectOne4" resultType="flower">            
select  *  from   flower  where  id=${a}  and name=${b}   
</select>

 

 

02测试文件

//【A】参数传递一
 Flower fl = session.selectOne("com.bjsxt.mapper.FlowerMapper.selectOne2", 1);
// 【B】参数传递二
Flower fl=new Flower();

fl.setId(1);

fl.setName("玫瑰花");

 Flower flower = session.selectOne("com.bjsxt.mapper.FlowerMapper.selectOne2", fl);
System.out.println(flower);
// 【C】参数传递三
 Map<String,Object>  map=new HashMap<>();
map.put("a", 1);
map.put("b", "'玫瑰花'");
Flower flo = session.selectOne("com.bjsxt.mapper.FlowerMapper.selectOne4", map);
System.out.println(flo);

[1]mybatisparameterType 这个属性可以省略的 但是 resultType 是不可以省略的

[2]#{}  相当于占位符   ${}  相当于拼接

 

第三节 MyBatis中增删改操作

01Mapper层代码

<!-- 增加操作  public  int   insert (Flower  fl)  -->    
<insert id="insert">        
    insert  into  flower  values(default,#{name},#{price},#{production})   
</insert>          
<!--修改操作  public  int  update(Flower fl) -->
<update id="update">            
 update  flower  set name=#{name},price=#{price},production=#{production} where  id=#{id}    
</update>
<!--删除操作  public  int delete(int id)  -->  
<delete id="delete">        
 delete   from  flower  where  id=#{param1}    
</delete>

 

02测试文件

Flower  fl =new Flower(6, "随便花123",50, "支付宝");  
//【A】添加操作                
 int update1 = session.insert("com.bjsxt.mapper.FlowerMapper.insert", fl);                                 
// 【B】修改操作                
int update2 = session.update("com.bjsxt.mapper.FlowerMapper.update", fl);                                
// 【C】删除操作                                
int update3 = session.delete("com.bjsxt.mapper.FlowerMapper.delete", 6);
session.commit();

 

 提交的两种方式

 [1]session.commit();   

 [2]SqlSession session = factory.openSession(true);

总结:Mybatis中默认事务是不提交的,所以在做完增删改操作后,要手动提交事务

 

第四节 MyBatisMapper代理方式

01Mapper 的动态代理作用

   目前使用sqlsession进行增删改查的缺点:

[1] 没有办法实现多参数的传递

Flower flower=sqlSession.slectOne("com.bjsxt.mapper.FlowerMapper.selectOne2", fl);    此语句只能进行单个参数的传递

    [2]书写的时候没有接口,后期的维护就比较的低 ,sqlsesssion的方式无须写接口,但不方便后期维护。

   解决的方案:

    Mapper的代理方式实现增删改查

02代码实现

接口代码

public interface FlowerMapper {
    //查询所有操作
    List<Flower>  selectAll();
    //修改操作
    int   insert(Flower  flower);
}

XML中文件

<!--namespace:必须是接口所在的全路径-->条件是使用mapper代理方式的话
<mapper namespace="com.bjsxt.mapper.FlowerMapper">
    <!--id的名称和接口中方法必须保持一致-->与接口建立了关系
    <select id="selectAll" resultType="flower">
          SELECT  *  from  flower
    </select>
    <insert id="insert">
        insert into flower values (DEFAULT ,#{name},#{price},#{production})
    </insert>
</mapper>

 

FlowerMapper mapper = sqlSession.getMapper(FlowerMapper.class);
//查询操作
List<Flower> list = mapper.selectAll();
//添加操作
Flower  f=new Flower();
f.setName("sxt");
f.setPrice(19);
f.setProduction("bj");
int insert = mapper.insert(f);
System.out.println(insert);

 

第五节 MyBatis中多参数传递

01接口中代码

//查询信息       
 public  Flower  selectOne(int id,String name);                
// 查询信息//@Param指的是起别名的意思        
 public  Flower  selectOne2(@Param("uu")int uu,@Param("oo")String ii);                
// 传递对象       
 public  Flower  selectOne3(Flower fl);                
// 传递对象        
 public  Flower  selectOne4(Flower fl,Flower fl2);

 

02Mapper文件

<select id="selectOne" resultType="flower">
    <!-- select *  from  flower where id=#{0} and name=#{1} -->
    <!-- map.put("param1",1)  map.put("param2",'玫瑰花')   -->
    select *  from  flower where id=#{param1} and name=#{param2}
</select>
<select id="selectOne2" resultType="flower">
select *  from  flower where id=#{uu} and name=#{oo}
</select>

<select id="selectOne3" resultType="flower">
select *  from  flower  where  id=#{id} and name=#{name}
</select>
<select id="selectOne4" resultType="flower">
select *  from  flower  where  id=#{param1.id} and name=#{param2.name}
</select>

 

 

 

注:<package name=com.bjsxt.mapper></package>

这是一种mapper文件自动扫描的写法,前提是接口名字要跟mapper中的xml名字一样才行。

第六节 MyBatis中动态SQL

01为什么使用sql语句的动态拼接    

  目前学习的内容sql语句都是直接写死的,但是在实际的开发过程中很多的sql语句都是根据不同的业务情况进行不同的改变的

02 解决的方案

    sql语句的动态拼接

03学习的标签

   if  where   when    set   trim   foreach   bind  include  sql

04 代码实现

4.1接口代码

public interface FlowerMapper {
    //按照条件查询
    List<Flower>  selectMore(String  name,String  production);
    //按照条件查询
    List<Flower>  selectMore2(String  name,String  production);
    List<Flower>  selectMore3(String  name);
    //按照条件查询
    List<Flower>  selectMore4(String  name,String  production);
    //修改操作
    int update(Flower  flower);
    //修改操作
    int update2(Flower  flower);
}

 

4.2 XML文件

<mapper namespace="com.bjsxt.mapper.FlowerMapper">

    <!--if标签
       if(test){..}
       if(test){..}
    -->
    <select id="selectMore" resultType="flower">
        SELECT  *  from   flower  where  1=1
        <!--OGNL表达式-->
        <if test="param1!=null and param1!=''">   //一对单引号代表空字符串                                       
            and  name=#{param1}
        </if>
        <if test="param2!=null and param2!=''">
            and  production=#{param2}
        </if>
    </select>

    <!--Where标签的作用:会自动的增加where关键字,并且会把多余的第一个and去掉-->

//功能跟上面是同样的效果
    <select id="selectMore2" resultType="flower">

        SELECT  *  from   flower
        <!--OGNL表达式-->
            <where>
                    <if test="param1!=null and param1!=''">
                         name=#{param1}
                    </if>

                    <if test="param2!=null and param2!=''">
                        and  production=#{param2}
                    </if>
            </where>
    </select>
     
    <select id="selectMore3" resultType="flower">

         SELECT  *  from  flower

         <where>

              <if test="param1!=null and param1!=''">
                   name=#{param1}
              </if>

         </where>

    </select>
    <!--
        if(){..}
        else if(){..}
        else if(){..}
        else {}
    -->
    <select id="selectMore4" resultType="flower">

        SELECT  *  from  flower

         <where>
                <choose>

                     <when test="param1!=null and param1!=''">
                           name=#{param1}
                     </when>

                     <when test="param2!=null and param2!=''">
                          and  production=#{param2}
                     </when>
                     <otherwise>
                         1=1
                     </otherwise>

                </choose>

         </where>

    </select>

    <!--Set 会自动增加set关键字,并且去除最后一个逗号-->
    <update id="update">
        UPDATE   flower
        <set>
            <if test="name!=null and  name!=''">
                name=#{name},
            </if>

            <if test="production!=null and production!=''">
                production=#{production},
            </if>

        </set>
         where id=#{id}

    </update>

    <!--
       trim:
          prefix:添加前缀
          prefixOverrides:去除前缀
          suffix:添加后缀
          suffixOverrides:去除后缀
    -->
    <update id="update2">

        UPDATE   flower

          <trim prefix="set" suffixOverrides=",">

                <if test="name!=null and  name!=''">
                    name=#{name},
                </if>

                <if test="production!=null and production!=''">
                    production=#{production}
                </if>
          </trim>

        where id=#{id}

    </update></mapper>

4.3测试代码

// 动态SQL语句
public static void main(String[] args) throws IOException {
    //[1]解析myBatis.xml文件
    InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
    //[2]获得sqlsession工厂
    SqlSessionFactory  factory=new SqlSessionFactoryBuilder().build(inputStream);
    //[3]获得session对象
    SqlSession sqlSession = factory.openSession(true);
    //[4]执行方法
    FlowerMapper mapper = sqlSession.getMapper(FlowerMapper.class);
    //List<Flower> list = mapper.selectMore4("玫瑰花","");
    Flower  f=new Flower();
    f.setId(9);
    mapper.update(f);
    //[5]关闭资源
    sqlSession.close();
}

 

 

 

代码实现二

public interface FlowerMapper2 {
    // map.put("list",li)  map.put("array",arr);
    List<Flower>  selectMore(List<Integer>  li);
    List<Flower>  selectMore2(String  name,String   production);
    List<Flower>  selectMore3(List<String>  li);
}

 

<mapper namespace="com.bjsxt.mapper.FlowerMapper2">
      <select id="selectMore" resultType="flower">
          SELECT  id,name,price  from  flower   where   id  in
          <foreach collection="list" open="(" separator="," close=")" item="it">
               #{it}
          </foreach>
      </select>
    <select id="selectMore3" resultType="flower">
        SELECT  id,name,price  from  flower   where   production  in
       <foreach collection="list" open="(" separator="," close=")" item="it">
            #{it}
        </foreach>
    </select>
      <select id="selectMore2" resultType="flower">
            SELECT  id,name,price  from  flower
            <where>
                  <if test="param1!=null and param1!=''">
                      <bind name="pa" value="'%'+param1+'%'"></bind>
                      name  like  #{pa}
                  </if>
                <if test="param2!=null and param2!=''">
                   and  production  like  '%${param2}%'
                </if>
            </where>
      </select>
     <!-- <select id="selectMore3"  resultType="flower">
           SELECT  <include refid="sq2"></include>    from  flower
      </select>
      <insert id="ins">
            insert into flower(id,name,price)   values (DEFAULT ,#{name})
      </insert>-->
       <!--定义[公共]的SQL代码片段-->
      <sql id="sq1">
             id,name,price
      </sql>

</mapper>

 

 

MyBatis第天】

一、 主要内容

1. MyBatis中的多表查询操作

2. MyBatis中缓存

3. ThreadLocal的实现

4. MyBatis中注解支持

5. MyBatis中底层实现

二、 学习目标

节数

知识点

要求

 

第一节(MyBatis中的多表查询

MyBatis中业务代码查询

了解

MyBatis中N+1方式

了解

MyBatis中多表查询SQL

掌握

第二节(MyBatis中缓存

MyBatis中一级缓存

掌握

MyBatis中二级缓存

掌握

第三节(ThreadLocal的实现)

ThreadLocal原理

掌握

ThreadLocal代码实现

掌握

第四节(MyBatis中注解的支持)

注解的使用

掌握

第五节(MyBatis中底层实现)

MyBatis中底层原理

掌握

 

第一节 MyBatis中多表查询

01多表查询的简介

[1]多表查询的操作

   学习到目前为止操作的都是一个表的增加、删除、修改、查询。在实际的开发中操作多表的情况比较多。

02 如何进行多表的查询

1业务代码的方式  

(实现的方式,书写业务逻辑的java代码实现)

查询学生所在班级的信息 (一对一查询)

1、先把所有学生查询出来(clazzno)

 select*  from  student

       2、拿着clazzno去clazz表中查询班级的信息 

select * from clazz where cno=?

       查询班级中所有学生的信息(一对多查询)

1、查询所有班级的信息(clazzno)

              Select *  from  clazz

2、查询指定班级中的所有学生---List

             Select *  from  student  where  clazzno=?

      特点:

        班级和学生之间的关系全部是靠我们书写java业务逻辑代码的方式实现的

        最后执行完成SQL语句都执行了N+1次数据的查询

     代码实现:  

clazzMapper

 

 

 

studentMapper

 

 

测试代码

 

 

 

2N+1查询方式

      [1]什么是N+1的查询方式

如果没有N+1的方式我们想要实现多表的查询,自己书写查询的业务逻辑代码(java)

      mybatis希望通过自己标签配置的方式来解决这个问题

      [2]执行的操作

        查询学生所在班级的信息(一对一)

        查询班级中所有学生的信息(一对多)

     使用的时候书写标签需要注意:

     查询出来返回的是一个对象:association

     查询出来返回的是一个集合:collection

 

    总结: 业务装配方式和N+1查询方式

        共同点:执行SQL语句的条数上都是N+1条语句

        不同点:

                业务装配方式:是我们自己书写java代码的方式进行配置的

                N+1方式:通过MyBatis标签配置的方式实现的

代码实现:

StudentMapper

 

 

 

 

ClazzMapper

 

 

 

 

 

3多表查询语句实现(重点)

        查询所有学生所在班级的信息(一对一)

        班级查询学生的操作(一对多)  

    遇到的问题:

      查询的SQL语句非常的简单,但是如何把查询的数据接受这个就是一个问题

       [1]把每一个实体中的字段拿出来组建成一个新的实体  返回还是resultType

              存在的问题:映射的内容会出现重复的字段

       [2] resultMap:映射的操作

   代码实现:

StudentMapper.xml

 

 

 

 

 

 

ClazzMapper.xml

 

 

4Auto_Mapping

     数据注入的方式   

     [1]自动注入方式  Auto_Mapping (自己封装的实体属性和数据库的字段是一样的情况Mybatis会自动的注入)

     [2]手动注入的方式  resultMap  

     作用:解决自己做的实体的封装和数据库的字段不一致的问题

5resultTyperesultMap使用场景

[1]如果你做的是单表的查询并且封装的实体和数据库的字段一一对应   resultType

[2]如果实体封装的属性和数据库的字段不一致  resultMap

[3]使用的是多表的联合查询  resultMap

[4]使用N+1查询的时候   resultMap

第二节  MyBatis中的缓存

01 Mybatis中的缓存简介

缓存的好处:只是查询才有缓存 (增删改没有缓存的),可以增访问的速度

 sqlsession级缓存 (一级缓存) 默认开启的

所有的操作是公用同一个SQLsession对象并且执行的是同一条SQL语句的时候才会走缓存

02缓存的缺点

        可能存在数据的脏读  

执行修改、删除、添加 默认的把缓存中数据全部清空

03问题

    不同的用户访问的时候创建了不同的sqlsession对象 ,这个时候我们缓存的数据没有办法实现共享

04sqlsession一级缓存,mybatis默认是打开的,二级缓存需要手动设置

使用SqlSession对象操作数据库资源时,SqlSession对象会先去其缓存区查找是否有现成的符合要求的数据,如果有则返回,没有则按照需求进行数据库操作获取符合要求的资源,并将资源返回给用户的同时在其缓存中缓存,当我们使用同一个SqlSession对象操作同一个Sql资源时,就可以从缓存中直接获取数据库资源数据了

 

 

05 factory的缓存(二级缓存)适用于同一个SqlSessionFactory对象,二级缓存为所有用户共享

 使用的方法:

[1] 在Mybatis.xml中开始二级缓存 <setting name="cacheEnabled" value="true"/>

[2] 在对应的mapper.xml文件中<cache readOnly="true"></cache>

[3]  关闭获得提交指定的sqlsesson对象

注意    当用户查询时,会先在Factory对象自己的缓存中(即二级缓存)查看是否有现成的数据,有则直接返回,没有则继续查看sqlSession中(即一级缓存)是否有,有则返回,没有则去数据库中获取资源,将资源返回的同时在SqlSession的缓存中缓存一份儿,(即先保存到一级缓存中)当该SqlSession对象被commit或者close时将其缓存的数据刷入到Factory中。

查询数据顺序  二级-->一级--->数据库--->把数据保存到一级,当sqlsession关闭或者提交的时候,把数据刷入到二级缓存中

 

第三节 ThreadLocal

01 遇到的问题

 

即可能出现这样一个情况,即用户的一个请求可能会嵌套调用多个sqlsession对象,造成资源的浪费

   如果我们做一个请求时候多次使用sqlsession对象这样就会造成sqlsession 浪费,也就是资源浪费,效率也会降低

   我们需要达到的目的就是用户发出的一个请求中实现sqlsession的共享 

即一个请求的过程中共用同一个sqlsession对象

   请求没有改变,线程就不会改变 

   最终的目的就是在同一个线程中实现数据sqlsession的共享 

02解决方案

   ThreadLoacl: 作用  在同一个线程中实现数据(sqlsession)的共享 

   底层使用的map集合  map.put(key,value);

                      map.put(线程的ID,conn)

即把线程的ID以及sqlsession对象存到map集合里面,就实现了同一个线程,共用同一个sqlsession对象。即同一个请求共用同一个sqlsession对象。

 

03代码实现

1. public class DBUtil {  

2.   

3.      private   static SqlSessionFactory factory;  

4.   

5.      private  static ThreadLocal<SqlSession>  tl=new ThreadLocal<>();  

6.   

7.       static {  

8.           InputStream inputStream = null;  

9.           try {  

10.               //[1]解析myBatis.xml文件  

11.               inputStream = Resources.getResourceAsStream("mybatis.xml");  

12.               //[2]获得sqlsession工厂  

13.                factory=new SqlSessionFactoryBuilder().build(inputStream);  

14.           } catch (IOException e) {  

15.               e.printStackTrace();  

16.           }  

17.       }  

18.       //获得sqlsession对象  

19.       public  static SqlSession   getSqlSession(){  

20.   

21.           //获得ThreadLoacl中的sqlsession对象  

22.           SqlSession sqlSession = tl.get();  

23.   

24.           if(sqlSession==null){  

25.   

26.                sqlSession = factory.openSession(true);  

27.   

28.                //把创建好的对象放到ThreadLoacl  

29.                tl.set(sqlSession);  

30.           }  

31.   

32.           return  tl.get();  

33.       }  

34.   

35.   

36.       //关闭sqlsession  

37.   

38.     public  static    void     closeAll(){  

39.   

40.         SqlSession sqlSession = tl.get();  

41.   

42.         if(sqlSession!=null){  

43.   

44.             sqlSession.close();  //sqlsession用完后要关闭

45.   

46.         }  

47.         tl.set(null);  //关闭sqlsession后清空里面的对象。

48.     }  

49.   

50. }  

 

第四节 MyBatis中的注解

01代码实现

1. @Select("select *  from  student")  

2. List<Student>  selectAll();  

3.   

4. @Select("select *  from  student where  sid=#{param1}")  

5. Student  selectOne(int id);  

6.   

7. @Insert("insert into  student   values(default,#{sname},#{clazzno})")  

8. int  insert(Student  student);  

9.   

10. @Update("update  student set  sname=#{sname} where  sid=#{sid}")  

11. int  update(Student  student);  

12.   

13. @Delete("delete  from  student  where sid=#{param1}")  

14. int  delte(int sid);  

直接在接口中的抽象方法上面写对应注解即注解sql语句,这样的话就不需要mapper.xml了。

02注解使用的优缺点

[1] 使用注解没有实现java代码sql语句的解耦

[2] 进行多表的查询比较的麻烦

[3] 无法实现sql语句的动态拼接

第五节 MyBatis中的原理

01Mybatis的运行原理

1. 运行过程中涉及到的类

1.1 Resources MyBatis中IO流的工具类

1.1 加载配置文件

1.2 SqlSessionFactoryBuilder() 构建器

1.2.1 作用:创建SqlSessionFactory接口的实现类

1.3 XMLConfigBuilder  MyBatis全局配置文件内容构建器类

1.3.1 作用负责读取流内容并转换为JAVA代码.

1.4 Configuration 封装了全局配置文件所有配置信息.

1.4.1 全局配置文件内容存放在Configuration中

1.5 DefaultSqlSessionFactory 是SqlSessionFactory接口的实现类

1.6 Transaction 事务类

16.1 每一个SqlSession会带有一个Transaction对象.

1.7 TransactionFactory 事务工厂

1.7.1 负责生产Transaction

1.8 Executor  MyBatis执行器

1.8.1 作用:负责执行SQL命令

1.8.2 相当于JDBC中statement对象(或PreparedStatement或CallableStatement)

1.8.3 默认的执行器SimpleExcutor

1.8.4 批量操作BatchExcutor

1.8.5 通过openSession(参数控制)

1.9 DefaultSqlSession 是SqlSession接口的实现类

1.10 ExceptionFactory MyBatis中异常工厂

02流程图

 

 

 

03文字解释

MyBatis运行开始时需要先通过Resources加载全局配置文件.下面需要实例化SqlSessionFactoryBuilder构建器.帮助SqlSessionFactory接口实现类DefaultSqlSessionFactory.

在实例化DefaultSqlSessionFactory之前需要先创建XmlConfigBuilder解析全局配置文件流,并把解析结果存放在Configuration中.之后把Configuratin传递给DefaultSqlSessionFactory.到此SqlSessionFactory工厂创建成功.

SqlSessionFactory工厂创建SqlSession.

每次创建SqlSession时,都需要由TransactionFactory创建Transaction对象,同时还需要创建SqlSession的执行器Excutor,最后实例化DefaultSqlSession,传递给SqlSession接口.

根据项目需求使用SqlSession接口中的API完成具体的事务操作.

如果事务执行失败,需要进行rollback回滚事务.

如果事务执行成功提交给数据库.关闭SqlSession

----------------------------------------------------------------------

[1] MyBatis的基本的操作

A、mybatis框架的基本搭建

B、使用sqlSESSION对数据进行CRUD

C、使用Mapper代理方式操作CRUD

[2] myBatis中动态SQL拼接

             Foreach  where  if   bind   set  

[3] mybatis中多表查询

A、业务代码

B、N+1查询

C、多表查询的SQL

[4] 其他知识

A、myBatis中缓存机制

B、ThreadLoacl

C、注解的使用

D、MyBatis中运行原理

 

 

posted @ 2021-11-17 17:33  日月笼中鸟乾坤水上萍  阅读(122)  评论(0)    收藏  举报