第二章-sql映射文件详解

飞一样的编程
飞一样的编程
擅长邻域:Java,MySQL,Linux,nginx,springboot,mongodb,微信小程序,vue

分类: ssm 专栏: ssm框架课 标签: sql映射文件

2022-11-28 11:13:11 726浏览

sql映射文件详解

1.sql映射文件

mybatis框架的主要思想是将sql语句从程序代码中分离出来,对jdbc访问数据库的代码进行封装,从程序中消除了所有sql参数设置以及处理结果集的jdbc代码。从而大量减少数据访问层的编码量,并且,sql语句与代码解耦,可以最大限度地实现对sql语句的灵活管理,方便sql调优以保证性能。

2.mybatis框架的条件查询

2.1实现单一的条件查询

示例1:根据用户的真实姓名模糊匹配查询用户信息

<select id="getUsersByRealName" resultType="cn.cvs.pojo.SysUser" parameterType="string">
  select * from t_sys_user where realName like CONCAT('%',#{realName},'%')
</select>

2.2实现多条件查询

1.将查询条件封装成Java对象作为入参

  <select id="getUsersByPojo" resultType="cn.cvs.pojo.SysUser" parameterType="cn.cvs.pojo.SysUser">
         select * from t_sys_user where realName like CONCAT('%',#{realName},'%') and roleId = #{roleId}
    </select>
SysUser user = new SysUser();
user.setRealName("李");
user.setRoleId(3);
List<SysUser> users = sqlSession.getMapper(SysUserMapper.class).getUsersByPojo(user);

2.将查询条件封装成map对象作为入参

   <select id="getUsersByMap" resultType="cn.cvs.pojo.SysUser" parameterType="map">
        select * from t_sys_user where realName like CONCAT('%',#{rName},'%') and roleId = #{rId}
    </select>
Map<String,Object> map = new HashMap<>();
map.put("rName","赵");
map.put("rId",2);
List<SysUser> sysUserList = sqlSession.getMapper(SysUserMapper.class).getUsersByMap(map);

3.使用@Param注解实现多参数入参

 public List<SysUser> getUsersByParam(@Param("realName") String realName,@Param("roleId") int roleId);
            List<SysUser> sysUsers = sqlSession.getMapper(SysUserMapper.class).getUsersByParam("赵", 2);

2.3实战训练

在724系统中实现查询入库记录表的功能

3.mybatis框架的结果映射

3.1使用resultMap元素自定义结果映射

查询用户信息列表,需要展示的字段包括账号 真实姓名 性别 电话 用户角色,注意:用户角色要显示角色名称而不是角色ID

SysUser实体类中增加属性:

private String userRoleName;//角色名称

<resultMap id="userWithRoleName" type="cn.cvs.pojo.SysUser">
        <id property="id" column="id"></id>
        <result property="userRoleName" column="roleName"></result>
    </resultMap>
    <select id="getUsersWithRoleName" resultType="cn.cvs.pojo.SysUser" resultMap="userWithRoleName">

        SELECT
            u.*,r.roleName
        FROM
            t_sys_user u
            LEFT JOIN t_sys_role r on u.roleId =r.id
        WHERE
            u.realName LIKE CONCAT(
                '%',
                #{realName},'%') and u.roleId = #{roleId}
    </select>

分析:resultMap元素包含以下属性:

  • id:映射规则集的唯一标识,可以被select元素的resultMap属性引用
  • type:映射的结果类型,一般指的是实体类的全类名

resultMap元素包含以下子元素

  • id:指定和数据表主键字段对应的标识属性,设置此项可提升mybatis的性能
  • result:指定结果集字段和实体类属性的映射关系

3.2实战训练

查询入库记录以及相关的供应商名称

3.3嵌套结果映射

1.association元素

association元素用来处理has-one类型的关系,如用户类内部“有一个”用户角色类型的属性。

例子:根据用户的角色id查询出用户的姓名,角色ID 角色编码和角色名称。

 <resultMap id="usersByRoleId" type="cn.cvs.pojo.SysUser">
        <id property="id" column="id"></id>
        <result property="realName" column="realName"></result>
        <association property="sysRole" javaType="cn.cvs.pojo.SysRole">
            <id property="id" column="rid"></id>
            <result property="code" column="code"></result>
            <result property="roleName" column="roleName"></result>
        </association>
    </resultMap>

    <select id="getUsersByRoleId" parameterType="integer" resultMap="usersByRoleId">
        SELECT
                u.*,r.id as rid, r.code, r.roleName
            FROM
                t_sys_user u
                LEFT JOIN t_sys_role r on u.roleId =r.id
            WHERE
                u.roleId = #{roleId}

    </select>
 @Test
    public  void  getUsersByRoleId(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.createSqlSession();
            List<SysUser> usersByRoleId = sqlSession.getMapper(SysUserMapper.class).getUsersByRoleId(2);
            for(SysUser user: usersByRoleId){
                logger.debug("用户名:"+user.getRealName()+"roleId:"+user.getSysRole().getId() + "角色编号"+user.getSysRole().getCode() +"角色名称:"+user.getSysRole().getRoleName());
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    }

association元素的主要属性如下:

  • property:实体类中用来映射查询结果子集的属性
  • JavaType:property指定的属性的数据类型

association元素包含如下子元素

  • d:指定和数据表主键字段对应的标识属性,设置此项可提升mybatis的性能
  • result:指定结果集字段和实体类属性的映射关系

2.collection元素

和association非常相似,association是一对一或者多对一,而collection是一对多。即实体类内部嵌套的是一个集合类型的属性。

例子:要求获取指定用户的信息和地址列表

 <resultMap id="userAndAdressByUserId" type="cn.cvs.pojo.SysUser">
        <id column="id" property="id"></id>
        <result property="account" column="account"></result>
        <result property="realName" column="realName"></result>
        <collection property="addressList" ofType="cn.cvs.pojo.Address">
            <id column="aid" property="id"></id>
            <result property="contact" column="contact"></result>
            <result property="addressDesc" column="addressDesc"></result>
            <result property="postCode" column="postCode"></result>
            <result property="tel" column="tel"></result>
        </collection>
    </resultMap>
    <select id="getUserAndAdressByUserId" resultMap="userAndAdressByUserId" parameterType="integer">
         SELECT
                u.*,a.id as aid, a.contact, a.addressDesc,a.postCode,a.tel
            FROM
                t_sys_user u
                LEFT JOIN t_address a on a.userId =u.id
            WHERE
                u.id = #{userId}

    </select>
sqlSession = MyBatisUtil.createSqlSession();
            SysUser user= sqlSession.getMapper(SysUserMapper.class).getUserAndAdressByUserId(2);

            logger.debug("用户账号account:"+user.getAccount()+"用户名称:"+user.getRealName());

            //遍历用户地址
            for(Address address : user.getAddressList()){
                logger.debug("address----->id:"+address.getId()
                +",contact:"+address.getContact()
                +",addressDesc:"+address.getAddressDesc()
                +",postCode:"+address.getPostCode()
                +",tel:"+address.getTel()
                );
            }

collection元素有如下常用属性

  • property:实体类中用来映射查询结果子集的集合属性
  • ofType:property指定的集合属性中的元素的数据类型,可以使用Java的全类名

3.4resultType和resultMap小结

resultType适用于比较简单,直接的数据封装场景。

resultMap处理结果集字段名与实体类属性名不一致,或需要对连接查询结果使用嵌套映射等较为复杂的问题。

3.5实战训练

  1. 在724系统中使用association元素查询入库记录表,在之前的基础上实现嵌套结果映射,查询并展示入库记录编码,商品名称,供货商编码,供货商名称,联系人,联系电话,商品总额,支付状态。
  2. 在724系统中使用collection查询供货商及相关入库记录

3.6resultMap的自动映射行为

resultMap自动映射的默认行为是对于没有嵌套映射的resultMap使用自动映射,对于有嵌套映射的resultMap则不使用自动映射,仅为手工映射的属性赋值。

可以在mybatis框架的核心配置文件中进行设置,修改自动映射的行为,

<!--设置自动映射行为-->
<setting name="autoMappingBehavior" value="FULL"/>

自动映射的三种行为:

  1. NONE:禁用自动映射,仅为手工映射的属性赋值
  2. PARTIAL:默认行为,对于没有嵌套映射的resultMap使用自动映射,而对于有嵌套映射的resultMap不使用自动映射,仅为手工映射的属性赋值
  3. FULL:全部使用自动映射,对有嵌套的resultMap也会自动映射。

4.mybatis的增,删,改操作

4.1执行insert语句

增加用户的方法,参数为要添加的用户实例。

<insert id="add" parameterType="cn.cvs.pojo.SysUser">
        insert  into t_sys_user (
            account,
            realName,
            password,
            sex,
            birthday,
            phone,
            address,
            roleId,
            createdUserId,
            createdTime,
            updatedUserId,
            updatedTime
        )
        VALUES (
            #{account},
            #{realName},
            #{password},
            #{sex},
            #{birthday},
            #{phone},
            #{address},
            #{roleId},
            #{createdUserId},
            #{createdTime},
            #{updatedUserId},
            #{updatedTime}
        )

    </insert>
    @Test
    public void testAdd(){
        SqlSession sqlSession = null;
        int count = 0;
        try{
            sqlSession =  MyBatisUtil.createSqlSession();
            SysUser user = new SysUser();
            user.setAccount("mayun");
            user.setRealName("马云");
            user.setRoleId(1);
            user.setAge(45);
            user.setPassword("123456");
            count=sqlSession.getMapper(SysUserMapper.class).add(user);
//            int i=2/0;
            sqlSession.commit();

        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            count =0;
        }finally {
            MyBatisUtil.closeSqlSession(sqlSession);
        }
        logger.debug("add user count:"+count);
    }

4.2执行update语句

根据用户ID修改用户信息的功能,

 <update id="update" parameterType="cn.cvs.pojo.SysUser">
        update
            t_sys_user
        set
         `account` = #{account},
         `realName` = #{realName},
         `password` = #{password},
         `sex` = #{sex},
         `birthday` = #{birthday},
         `phone` = #{phone},
         `address` = #{address},
         `roleId` = #{roleId},
         `updatedUserId` = #{updatedUserId},
         `updatedTime` = #{updatedTime}
        WHERE
            (`id` = #{id});

    </update>

4.3执行delete语句

根据用户ID删除用户

   <delete id="delete" parameterType="integer">
        delete from t_sys_user where id = #{id}
    </delete>

4.4实战训练

在724系统中实现对供货商表的增,删, 改操作

5.mybatis框架的缓存

5.1缓存分类

1.一级缓存

基于PerpetualCache的hashMap本地缓存,默认是sqlsession级别的缓存,在sqlsession的生命周期内有效,当sqlsession关闭后,该sqlsession中所有的一级缓存会被清空。mybatis框架的一级缓存默认是开启的。

2.二级缓存

是sqlSessionFactory级别的,作用域超出了一个sqlsession的范围,缓存中的数据可以被所有sqlsession共享,mybatis框架的二级缓存默认是关闭的,使用的时候需要在mybatis框架的核心配置文件中设置开启。

5.2二级缓存的使用方法

1.在mybatis的核心配置文件中设置全局开启二级缓存。

<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>

2.即使全局开启了二级缓存,默认情况下也是不使用二级缓存的,可以根据需要在sql映射文件中配置,为当前namespace启用二级缓存。

<mapper namespace="cn.cvs.dao.SysUserMapper">
    <cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true"
    >
        
    </cache>

cache元素中各种属性的作用如下:

  • eviction:选择缓存回收策略(FIFO:先进先出,按照对象进入缓存的顺序来移除他们,这里推荐使用LRU策略:最近最少使用的)
  • flushInterval:设定缓存刷新间隔,以毫秒为单位设定缓存多长时自动刷新一次,默认不自动刷新。
  • size:设定缓存中最多存放多少个对象,默认是1024
  • readOnly:设定缓存数据是否只读,默认是false,表示缓存数据会用于读写操作,true表示缓存数据只用于读操作。

3.在sql映射文件中配置支持二级缓存后,如需对个别查询进行调整,可以在select元素中单独设置

<select id="count" resultType="integer" useCache="false">
        ……
    </select>

注意:二级缓存开启后,实体类一定要实现序列化接口,因为缓存要读取到内存中。

一级缓存默认开启,怎么演示:

查询两次一模一样的sql语句

List<SysUser> all =sysUserDao.getUserAndAdressByUserId(2L);
 System.out.println("=======================================");
List<SysUser> all2 =sysUserDao.getUserAndAdressByUserId(2L);

一级缓存失效,一级缓存不能跨sqlsession

       List<SysUser> all =sysUserDao.getUserAndAdressByUserId(2L);

            MybatisUtils.closeSession(sqlSession);
            System.out.println("=======================================");

            sqlSession=MybatisUtils.getSession();
            sysUserDao = sqlSession.getMapper(SysUserDao.class);
            List<SysUser> all2 =sysUserDao.getUserAndAdressByUserId(2L);

当开启二级缓存的时候,就可以跨sqlsession了。

6.课堂视频教程

https://www.bilibili.com/video/BV1TR4y1Z7np?p=2

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695