JavaWeb笔记(23)-mybatis缓存与注解

  1. mybatis中的延迟加载
1. 问题出现:
    a. 在一对多关联中:用户表与账户表
        1. 如果一个用户含有数量庞大的账户,则查询用户信息时,是否需要将其List<Account>查询出来?
            * 我们希望不使用账户信息时,查询用户信息则仅不在内存中查询存储List<Accout>
            * 只有在使用账户信息时,才查询List<Account>信息
        2. 如果查询一个账户信息时,是否需要将其所属的用户信息查询出来?
            * 我们希望在显示账户信息时,同时显示用户的部分信息,如姓名,年龄等
2. mybatis中的延迟加载:
    a. 延迟加载:
        只有在真正使用数据时才发起查询,不使用时不查询。按需加载
    b. 立即加载:
        不管是否使用信息,只要有关联,则立即查询所有信息
    c. 表间关系与适用场景:
        1. 一对多/多对多:
            通常采用延迟加载
        2. 多对一/一对一:
            通常采用立即加载
  1. 一对一的延迟加载
1. 设置开启延迟加载功能:
    修改配置文件SqlMapConfig.xml:
        在标签<configuration>中添加:
            <settings>
                <setting name="lazyLoadingEnabled" value="true"/>
                <setting name="aggressiveLazyLoading" vaule="false"/>
            </settings>
2. 查询账户信息,延迟查找其所属的用户信息
    a. 配置IAccountDao.xml文件:
        1. 配置findAll的抽象方法的select
            * 由于延迟查询所属用户信息,因此当前select标签中sql语句仅查询account信息
            <select id="findAll" resultMap="accountUserMap">
                select * from account 
            </select>
        2. 配置IAccountDao.xml中的resultMap标签
            * 由于延迟查询所属用户信息,因此在association标签中不再配置数据的封装
                <!--最外层的type依旧为账户类的类型(用户类引用封装在该类中),此处使用了别名-->
                <resultMap id="accountUserMap" type="accout">
                    <!--账户表主键-->
                    <id property="id" column="id"></id>
                    <!--账户表非主键-->
                    <result property="uid" column="uid"></result>
                    <result property="money" column="money"></result>
                    <!--配置账户表中一对一映射关系,使用association标签,封装user的内容-->
                    <!--其中property为账户类中用户类成员变量的属性名,column属性为关联的对对应的外键列-->
                    <!--javaType表示association标签内的数据封装为的实体类全限定类名(可以使用别名)-->
                    <association property="user" column="uid" javaType="user" select="cn.mysilent.dao.IUserDao.findUserById">
                        <!--内部不再需要封装数据-->
                        <!--延迟查询添加select属性,表示调用IUserDao中的id为findUserById的select标签查询-->
                        <!--findUserById中传入的id参数为column属性的值,即使用账户表中uid去查-->
                    </association>
                </resultMap>
        3. 配置IUserDao.xml中的select标签:
            * 延迟查询,当需要用户信息时,则会调用id为findUserById的select标签
            * 因此,在IUserDao.java中需要提供该抽象方法,在IUserDao.xml中配置该查询语句
                <!--此处根据id查询用户信息,返回的参数类型为user类型(resultType属性值)-->
                <select id="findUserById" parameterType="Integer" resultType="user">
                    <!--每次调用该标签时,传入查询的id值-->
                    select * from user where id=#{id}
                </select>
            * 添加抽象方法:
                User findUserById(Integer id);
3. 当仅查询账户信息时,并不会查询用户信息,只有当需要用户信息时,才会调用相应的IUserDao中的方法进行延迟查询
  1. 一对多的延迟加载
1. 设置开启延迟加载功能:
    修改配置文件SqlMapConfig.xml:
        在标签<configuration>中添加:
            <settings>
                <setting name="lazyLoadingEnabled" value="true"/>
                <setting name="aggressiveLazyLoading" vaule="false"/>
            </settings>
2. 查询用户信息,延迟查找其所包含的所有账户信息
    a. 配置IUserDao.xml文件:
        1. 配置findAll的抽象方法的select
            * 由于延迟查询所包含账户信息,因此当前select标签中sql语句仅查询user信息
            <select id="findAll" resultMap="userAccountMap">
                select * from user 
            </select>
        2. 配置IUserDao.xml中的resultMap标签
            * 由于延迟查询所包含账户信息,因此在collection标签中不再配置数据的封装
                <!--最外层的type依旧为账户类的类型(用户类引用封装在该类中),此处使用了别名-->
                <resultMap id="userAccountMap" type="accout">
                    <!--用户表主键-->
                    <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>
                    <!--配置用户表中一对多映射关系,使用collection标签,表示封装的是一个集合-->
                    <!--其中property为用户类中账户类列表成员变量的属性名-->
                    <!--ofType表示集合内的数据封装为的实体类全限定类名(可以使用别名)-->
                    <collection property="accounts" ofType="account" select="cn.mysilent.dao.IAccountDao.findAccountByUid" column="id">
                        <!--
                        内部不再需要封装数据
                        延迟查询添加select属性,表示调用IAccountDao中的id为findAccountByUid的select标签查询
                        findAccountByUid中传入的uid参数为column属性的值,即使用用户表中的id去查
                        -->
                    </collection>
                </resultMap>
        3. 配置IAccountDao.xml中的select标签:
            * 延迟查询,当需要账户信息时,则会调用id为findAccountByUid的select标签
            * 因此,在IAccountDao.java中需要提供该抽象方法,在IAccountDao.xml中配置该查询语句
                <!--此处根据uid查询账户信息,返回的参数类型为user类型(resultType属性值)-->
                <select id="findAccountByUid" parameterType="Integer" resultType="account">
                    <!--每次调用该标签时,传入查询的id值-->
                    select * from account where uid=#{uid}
                </select>
            * 添加抽象方法:
                List<Account> findAccountByUid(Integer uid);
3. 当仅查询用户信息时,并不会查询所含账户信息
    只有当需要账户信息时,才会调用相应的IAccountDao中的方法进行延迟查询
  1. mybatis中的缓存
1. 缓存使用:
    a. 减少数据库的交互,提高执行效率
    b. 数据经常查询且不经常改变
    c. 数据的正确性与否对最终结果影响不大
2. mybatis中的缓存:
    a. 一级缓存:
        * 指的是mybatis中SqlSession对象的缓存:
            当执行查询后,查询结果会同时存储到SqlSession对象的一个map区域中
            当再次查询相同的数据,有现在SqlSession对象中查询是否含有该数据,有则直接取出
            当SqlSession对象销毁时,一级缓存释放
        * 发起两次相同的查询时,可以通过日志发现仅向数据库发起第一次查询
            可以使用SqlSession对象的clearCache()方法清空缓存
        * SqlSession对象调用更新,插入,删除,commit,close方法时,会清空一级缓存
    b. 二级缓存:
        * 指的是mybatis中SqlSessionFactory对象的缓存:
            由同一个SqlSessionFactory创建的SqlSession对象共享该缓存
        * 二级缓存使用步骤:
            1. 让mybatis框架支持二级缓存    --  在SqlMapConfig.xml中配置
                添加setting配置标签
                <settings>
                    <setting name="cacheEnabled" value="true"/>
                </settings>
            2. 让当前的映射文件支持二级缓存 --  在IUserDao.xml中配置
                添加cache配置标签
                <cache/>
            3. 让当前的操作支持二级缓存     --  在select标签中配置
                在select属性中添加useCache="true"
        * 二级缓存中存放的是数据,而非对象
            对象是在SqlSession对象中封装,尽管不同的SqlSession对象进行相同查询在日志中仅查询了一次数据库
            但是查询的结果的地址值是不相等的
            而一级缓存由于是同一个SqlSession对象内封装的对象,因此多次重复查询的对象地址值相同
  1. mybatis注解开发:
1. 原始配置文件有SqlMapConfig.xml和对应mappers的xml配置文件
2. 使用注解开发即使用注解来配置关于mappers的xml配置文件中的内容,SqlMapConfig.xml仍然需要配置
3. 使用步骤:
    a. 创建SqlMapConfig.xml配置文件,填写相关配置信息
    b. 在SqlMapConfig.xml的mappers中使用package标签配置带有注解的包
    c. mybatis中针对CRUD提供了4中注解@SELECT@UPDATE@INSERT@DELETE
    d. 在每个注解中写入sql语句
4. 在mybatis开发中,如果使用了注解,还配置了映射的xml文件,则会报错。
    解决方案:删除映射的xml配置文件
5. @Results@Result注解:
    解决表列名和实体类的属性名称对应不上问题
    @Select("select * from user ")
    @Results(value={
        @Result(id=true, property="实体类属性名", column="数据库表列名"),
        @Result(id=false, property="实体类属性名", column="数据库表列名"),
        @Result(id=false, property="实体类属性名", column="数据库表列名"),
        ...
    })
    List<User> findAll();
6. 在Results注解中还包含有一个id属性,用于为该Results起一个别名
    这样其他方法可以引用该Results配置,引用使用ResulMap注解,参数传入Results注解id属性值
    @Select("select * from user ")
    @Results(id="resultMap1", value={
        @Result(id=true, property="实体类属性名", column="数据库表列名"),
        //idw为true表示为主键
        ...
    })
    List<User> findAll();
    
    @Select("select * from user where id=#{id} ")
    @ResultMap(value={"resultMap1"})
    User findUserById(Integer id);
    
    //当插入语句中的参数和形参列表中的参数具有多个时,使用@Param注解标注该参数对应语句中哪个参数
    @Insert("insert into users_role(userId,roleId) values(#{uid}, #{rId})")
    void addRoleToUser(@Param("uid") String userId, @Param("rId") String roleId);
  1. mybatis多表查询注解开发
1. 一对一(多对一)关联:
    示例:查询账户信息,同时获取该账户所属的用户信息
    使用查询的注解配置:
        * 类似IAccountDao.xml中配置一样,在注解@Results中配置一个结果集
        *@Result注解中定义有One类型的注解@One和Many类型的注解@Many
        * 在一对一的@Result注解中,使用@One配置,@One注解中定义了select()
        * select()与IAccountDao.xml中select属性的作用一致,用于调用所指向的唯一查询方法
        * @One注解中还定义了一个FetchType类型的数值,用于标识是否延迟LAZY(延迟)EAGER(立即),DEFAULT
        * 一对一应该使用立即而非延迟,一对多使用延迟查询
        IAccountDao.java文件:
        @Select("select * from account ")
        @Results(value={
            @Result(id=true, property="id", column="id"),//设置id属性为true表示为主键,默认为false
            @Result(property="uid", column="uid"),
            @Result(property="money", column="money"),
            //接下来配置账户信息与用户信息的一对一关系
            //property为Account类中的User对象的引用名称
            //column为通过Account表中哪个值来关联查询
            //one表示这是一对一的关联关系
            @Result(property="user", column="uid", 
                //定义关联查询时该调用的方法
                one=@One(select="cn.mysilent.dao.IUserDao.findById", fetchType=FetchType.EAGER))
        })
        在IUserDao.java文件中需要提供对应的findById查询方法:
        @Select("select * from user where id=#{id} ")
        User findById(Integer id);
2. 一对多(多对多)关联:
    示例:查询用户信息,同时获取该用户所包含的所有账户信息
    使用查询的注解配置:
        * 类似IUserDao.xml中配置一样,在注解@Results中配置一个结果集
        *@Result注解中定义有One类型的注解@One和Many类型的注解@Many
        * 在一对多的@Result注解中,使用@Many配置,@Many注解中定义了select()
        * select()与IUserDao.xml中select属性的作用一致,用于调用所指向的唯一查询方法
        * @Many注解中还定义了一个FetchType类型的数值,用于标识是否延迟LAZY(延迟)EAGER(立即),DEFAULT
        * 一对一应该使用立即而非延迟,一对多使用延迟查询
        IUserDao.java文件中:
        @Select("select * from user ")
        @Results(value={
            @Result(id=true, property="id", column="id"),//设置id属性为true表示为主键,默认为false
            @Result(property="name", column="name"),
            @Result(property="address", column="address"),
            @Result(property="sex", column="sex"),
            @Result(property="birthday", column="birthday"),
            //接下来配置用户信息与账户信息的一对多关系
            //property为User对象中Account对象引用集合名称
            //column为通过User表中哪个值来关联查询
            //many表示这是一对多的关联关系
            @Result(property="accounts", column="id", 
                //定义关联查询时该调用的方法
                many=@Many(select="cn.mysilent.dao.IAccountDao.findAccountByUid", fetchType=FetchType.LAZY))
        })
        在IAccountDao.java文件中需要提供对应的findAccountByUid查询方法:
        @Select("select * from account where uid=#{uid} ")
        List<Account> findAccountByUid(Integer uid);
  1. 使用注解时开启二级缓存使用:
1. 在xml配置中使用二级缓存步骤为:
    a. 让mybatis框架支持二级缓存    --  在SqlMapConfig.xml中配置
        添加setting配置标签
        <settings>
            <setting name="cacheEnabled" value="true"/>
        </settings>
    b. 让当前的映射文件支持二级缓存 --  在IUserDao.xml中配置
        添加cache配置标签
        <cache/>
    c. 让当前的操作支持二级缓存     --  在select标签中配置
        在select属性中添加useCache="true"
2. 当使用注解配置使用二级缓存时步骤为:
    a. 让mybatis框架支持二级缓存    --  在SqlMapConfig.xml中配置
        添加setting配置标签
        <settings>
            <setting name="cacheEnabled" value="true"/>
        </settings>
    b. 在需要使用二级缓存的接口定义上方添加注解@CacheNamespace,设置blocking属性为true
        @CacheNamespace(blocking=true)
        public Interface IUserDao {
            //...
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值