>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring》、《Spring Cloud Alibaba微服务开发零基础入门到实操》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 26732 个阅读者 刷新本主题
 * 贴子主题:  mybatis的缓存和注解开发 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-01-28 15:35:47     消息  查看  搜索  好友  邮件  复制  引用

                  

mybatis的缓存和注解开发

  • mybatis中的加载时机(查询的时机)
  • mybatis中的一级缓存和二级缓存
  • mybatis的注解开发
  • 单表CRUD
  • 多表查询

   一、内容概要

1、Mybatis中的延迟加载
问题:在一对多中,当我们有一个用户,它有100个账户。
       在查询用户的时候,要不要把关联的账户查出来?
       在查询账户的时候,要不要把关联的用户查出来?
  
       在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询的。
       在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来。

什么是延迟加载:  在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)

什么是立即加载:  不管用不用,只要一调用方法,马上发起查询。

在对应的四种表关系中:一对多,多对一,一对一,多对多
  一对多,多对多:通常情况下我们都是采用延迟加载。
  多对一,一对一:通常情况下我们都是采用立即加载。

2、Mybatis中的缓存
什么是缓存:   存在于内存中的临时数据。
为什么使用缓存:  减少和数据库的交互次数,提高执行效率。

什么样的数据能使用缓存,什么样的数据不能使用:

    适用于缓存:
      经常查询并且不经常改变的。
      数据的正确与否对最终结果影响不大的。

    不适用于缓存:
       经常改变的数据
      数据的正确与否对最终结果影响很大的。
     例如:商品的库存,银行的汇率,股市的牌价。

Mybatis中的一级缓存和二级缓存
  一级缓存:

   它指的是Mybatis中SqlSession对象的缓存。
   当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
   该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中
   查询是否有,有的话直接拿出来用。
   当SqlSession对象消失时,mybatis的一级缓存也就消失了。
  
  二级缓存:

   它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

   二级缓存的使用步骤:
    第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
    第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
    第三步:让当前的操作支持二级缓存(在select标签中配置)

3、Mybatis中的注解开发                    

  二、Mybatis中的延迟加载

     1.一对一实现延迟加载

     IAccountDao.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="net.javathinker.dao.IAccountDao">

    <!-- 定义封装account和user的resultMap -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid"  column="uid"></result>
        <result property="money" column="money"></result>
        <!--  一对一的关系映射:配置封装user的内容
        select属性指定的内容:查询用户的唯一标识:
        column属性指定的内容:用户根据id查询时,所需要的参数的值
        -->
        <association property="user"  column="uid" javaType="user"  select="net.javathinker.dao.IUserDao.findById"></association>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="accountUserMap">
        select *  from account
    </select>

    <!-- 根据用户id查询账户列表 -->
    <select id="findAccountByUid" resultType="account">
        select * from account where uid =  #{uid}
    </select>

</mapper>

                   SqlMapConfig.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>
    <!-- 配置properties-->
    <properties resource="jdbcConfig.properties"></properties>

    <!--配置参数-->
     <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>

    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        < package name="net.javathinker.domain"></ package>
    </typeAliases>

    <!--配置环境-->
    <environments  default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" 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>
    <!-- 配置映射文件的位置 -->
    <mappers>
        < package name="net.javathinker.dao"></ package>
    </mappers>
</configuration>

                   2.多对多实现延迟加载

     IUserDao.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="net.javathinker.dao.IUserDao">

    <!-- 定义User的resultMap-->
    <resultMap id="userAccountMap" type="user">
        <id property="id"  column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <!-- 配置user对象中accounts集合的映射 -->
      (批注:在映射配置文件中 调用相关联的一方的根据id查询的方法)
        <collection property="accounts" ofType="account" select="net.javathinker.dao.IAccountDao.findAccountByUid"  column="id"></collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select *  from user
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user">
        select * from user where id =  #{uid}
    </select>

</mapper>

    三、Mybatis中的缓存

     1.测试一级缓存

  /**
     * 测试一级缓存
      */

    @Test
     public  void  testFirstLevelCache(){
        User user1 = userDao.findById(41 );
        System.out.println(user1);

//         sqlSession.close();
         // 再次获取SqlSession对象
//         sqlSession = factory.openSession();

        sqlSession.clearCache(); // 此方法也可以清空缓存

   userDao = sqlSession.getMapper(IUserDao. class );

        User user2 = userDao.findById(41 );
        System.out.println(user2);

        System.out.println(user1 ==  user2);
    }

       一级缓存是SqlSession范围的缓存,当调用SqlSession的修改,添加,删除,commit(),close()等 方法时,就会清空一级缓存。

          2.测试二级缓存

         第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.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>
    <!-- 配置properties-->
    <properties resource="jdbcConfig.properties"></properties>

     <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    
    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        < package name="net.javathinker.domain"></ package>
    </typeAliases>

    <!--配置环境-->
    <environments  default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" 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>
    <!-- 配置映射文件的位置 -->
    <mappers>
        < package name="net.javathinker.dao"></ package>
    </mappers>
</configuration>

                           第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)

         第三步:让当前的操作支持二级缓存(在select标签中配置)

<?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="net.javathinker.dao.IUserDao">
    <!--开启user支持二级缓存 默认为true-->
     <cache/>  

    <!-- 查询所有 -->
    <select id="findAll" resultType="user">
        select *  from user
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user"  useCache="true">
        select * from user where id =  #{uid}
    </select>

    <!-- 更新用户信息-->
    <update id="updateUser" parameterType="user">
        update user set username=#{username},address=#{address} where id= #{id}
    </update>
</mapper>

                   点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小                  

      四、Mybatis中的注解开发

       1.环境搭建

      2.单表CRUD操作(代理Dao方式)

     sqlMapConfig.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>
    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!--配置别名-->
    <typeAliases>
        < package name="net.javathinker.domain"></ package>
    </typeAliases>
    <!-- 配置环境-->
    <environments  default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" 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>
    <!-- 指定带有注解的dao接口所在位置 -->
    <mappers>
        <mapper  class="net.javathinker.dao.IUserDao"></mapper>
      或者
    <package name="net.javathinker.dao"></package>

    </mappers>
</configuration>

     IUserDao

package  net.javathinker.dao;

import  net.javathinker.domain.User;
import  org.apache.ibatis.annotations.Delete;
import  org.apache.ibatis.annotations.Insert;
import  org.apache.ibatis.annotations.Select;
import  org.apache.ibatis.annotations.Update;

import  java.util.List;

/**

* 在mybatis中针对,CRUD一共有四个注解
*  @Select @Insert @Update @Delete
  */

public  interface  IUserDao {

     /**
     * 查询所有用户
     *  @return
      */

    @Select("select * from user" )
    List<User>  findAll();

     /**
     * 保存用户
     *  @param  user
      */

    @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})" )
     void  saveUser(User user);

     /**
     * 更新用户
     *  @param  user
      */

    @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}" )
     void  updateUser(User user);

     /**
     * 删除用户
     *  @param  userId
      */

    @Delete("delete from user where id=#{id} " )
     void  deleteUser(Integer userId);

     /**
     * 根据id查询用户
     *  @param  userId
     *  @return
      */

    @Select("select * from user  where id=#{id} " )
    User findById(Integer userId);

     /**
     * 根据用户名称模糊查询
     *  @param  username
     *  @return
      */

//     @Select("select * from user where username like #{username} ")
    @Select("select * from user where username like '%${value}%' " )
    List<User>  findUserByName(String username);

     /**
     * 查询总用户数量
     *  @return
      */

    @Select("select count(*) from user " )
     int  findTotalUser();
}

                            3.多表查询操作

     使用注解来解决实体类属性与数据库表列名对应不上的问题

    /**
     * 查询所有用户
     *  @return
      */

    @Select("select * from user" )
    @Results(id="userMap",value= {
            @Result(id= true,column = "id",property = "userId" ),
            @Result(column = "username",property = "userName" ),
            @Result(column = "address",property = "userAddress" ),
            @Result(column = "sex",property = "userSex" ),
            @Result(column = "birthday",property = "userBirthday" ),
            
    })
    List<User> findAll();

                   mybatis注解开发一对一的查询配置

public  interface  IAccountDao {

     /**
     * 查询所有账户,并且获取每个账户所属的用户信息
     *  @return
      */

    @Select("select * from account" )
    @Results(id="accountMap",value =  {
            @Result(id= true,column = "id",property = "id" ),
            @Result(column = "uid",property = "uid" ),
            @Result(column = "money",property = "money" ),
            @Result(property = "user", column = "uid",one= @One(select="net.javathinker.dao.IUserDao.findById",fetchType=  FetchType.EAGER))
    })
    List<Account>  findAll();

     /**
     * 根据用户id查询账户信息
     *  @param  userId
     *  @return
      */

    @Select("select * from account where uid = #{userId}" )
    List<Account>  findAccountByUid(Integer userId);
}

                   mybatis注解开发一对多的查询配置

package net.javathinker.dao;

import  net.javathinker.domain.User;
import org.apache.ibatis.annotations.* ;
import  org.apache.ibatis.mapping.FetchType;

import  java.util.List;

    @CacheNamespace(blocking =  true )
public  interface  IUserDao {

     /**
     * 查询所有用户
     *  @return
      */

    @Select("select * from user" )
    @Results(id="userMap",value= {
            @Result(id= true,column = "id",property = "userId" ),
            @Result(column = "username",property = "userName" ),
            @Result(column = "address",property = "userAddress" ),
            @Result(column = "sex",property = "userSex" ),
            @Result(column = "birthday",property = "userBirthday" ),
            @Result(property = "accounts",column = "id" ,
                    many = @Many(select = "net.javathinker.dao.IAccountDao.findAccountByUid" ,
                                fetchType =  FetchType.LAZY))
    })
    List<User>  findAll();

     /**
     * 根据id查询用户
     *  @param  userId
     *  @return
      */

    @Select("select * from user  where id=#{id} " )
    @ResultMap("userMap" )
    User findById(Integer userId);

     /**
     * 根据用户名称模糊查询
     *  @param  username
     *  @return
      */

    @Select("select * from user where username like #{username} " )
    @ResultMap("userMap" )
    List<User>  findUserByName(String username);

    }

                   4. 缓存的配置

                        第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.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>
    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!--配置开启二级缓存-->
      <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>


    <!--配置别名-->
    <typeAliases>
        < package name="net.javathinker.domain"></ package>
    </typeAliases>
    <!-- 配置环境-->
    <environments  default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" 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>
    <!-- 指定带有注解的dao接口所在位置 -->
    <mappers>
       < package name="net.javathinker.dao"></ package>
    </mappers>
</configuration>

                           第二步:让当前的操作支持二级缓存(在select标签中配置)

@CacheNamespace(blocking =  true )
public  interface  IUserDao {

     /**
     * 查询所有用户
     *  @return
      */

    @Select("select * from user" )
    @Results(id="userMap",value= {
            @Result(id= true,column = "id",property = "userId" ),
            @Result(column = "username",property = "userName" ),
            @Result(column = "address",property = "userAddress" ),
            @Result(column = "sex",property = "userSex" ),
            @Result(column = "birthday",property = "userBirthday" ),
            @Result(property = "accounts",column = "id" ,
                    many = @Many(select = "net.javathinker.dao.IAccountDao.findAccountByUid" ,
                                fetchType =  FetchType.LAZY))
    })
    List<User> findAll();

     测试方法

   @Test
     public  void  testFindOne(){
        SqlSession session =  factory.openSession();
        IUserDao userDao = session.getMapper(IUserDao. class );
        User user = userDao.findById(57 );
        System.out.println(user);

        session.close(); // 释放一级缓存

        SqlSession session1 = factory.openSession(); // 再次打开session
        IUserDao userDao1 = session1.getMapper(IUserDao. class );
        User user1 = userDao1.findById(57 );
        System.out.println(user1);

            session1.close();

    }

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ----------------------------
原文链接:https://www.cnblogs.com/lsk-130602/p/12202311.html

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-01-29 17:58:50 重新编辑]
  Java面向对象编程-->输入与输出(下)
  JavaWeb开发-->Web运作原理(Ⅳ)
  JSP与Hibernate开发-->立即检索和延迟检索策略
  Java网络编程-->对象的序列化与反序列化
  精通Spring-->组合(Composition)API
  Vue3开发-->Vue Router路由管理器
  MyBatis+Spring 事务管理
  Mybatis Plus 多租户架构(Multi-tenancy)实现
  Mybatis-plus大数据量流式查询
  @Configuration注解的用法
  Spring MVC中自定义国家化LocaleResolver
  HandlerInterceptor与WebRequestInterceptor的异同
  【项目实践】后端接口统一规范的同时,如何优雅地扩展规范
  @ModelAttribute注解用法详解
  Spring MVC数据验证
  Spring Cloud构建微服务架构的断路器
  RESTful API的最佳设计原则
  Spring Boot集成EHCache实现缓存机制
  kubernetes 中的资源
  Spring Boot集成shiro ehcache(使用shiro的缓存管理)
  Spring配置日志
  更多...
 IPIP: 已设置保密
楼主      
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。