SQL映射XML文件

发布于:2022-12-18 ⋅ 阅读:(387) ⋅ 点赞:(0)

SQL映射的XML文件

mapper 

映射文件的根元素节点,只有一个属性namespace(命名空间)

namespace和子元素id联合保证唯一,区别不同的mapper

注:namespace的命名必须要跟某个DAO接口同名,同属DAO层,故代码结构上,映射文件与该DAO接口应放置在统一package下(如com.msds.dao),并且习惯上都以Mapper结尾(UserMapper.java、UserMapper.xml)

在不同的mapper文件中,子元素的id可以相同,MyBatis通过namespace和子元素的id联合区分。接口中的方法与映射文件中的SQL语句id应一一对应

使用select完成单一条件查询

select是MyBatis中最常用的元素之一


Dao接口


    //根据用户名称查询用户列表  模糊查询
    List<User> getUserListByName(String name);

Dao接口映射文件


    <!--根据用户名称查询用户列表  模糊查询-->
    <select id="getUserListByName" resultType="user" parameterType="string">
        SELECT * FROM smbms_user WHERE userName LIKE CONCAT ('%',#{name},'%')
    </select>


id:命名空间唯一的标识符、接口中的方法与映射文件中的SQL语句id一一对应

parameterType:传入SQL语句的参数类型

resultType:SQL语句返回值类型的完整类型名或别名

参数传递------>#{参数名}

注:数据库表的字段名与JavaBean的属性名一致

 使用select完成多条件查询

方式一:传递的参数是简单数据类型 

Dao接口
    //根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是基础数据类型    List<User> getUserListByNameAndRole1(@Param("xm") String name,@Param("js") Integer role);
Dao接口映射文件

    <!--根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是基础数据类型-->

    <select id="getUserListByNameAndRole1" resultType="user">

     SELECT * FROM smbms_user WHERE userName LIKE CONCAT ('%',#{xm},'%') 
            AND userRole=#{js}
    </select>

 

方式二:传递的参数是对象 

Dao接口 
   //根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是对象 

   List<User> getUserListByNameAndRole2User(User user);
Dao接口映射文件

    <!--根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是对象   #{对象的属性名}-->

    <select id="getUserListByNameAndRole2User" resultType="user" parameterType="user">

        SELECT * FROM smbms_user WHERE userName LIKE CONCAT ('%',#{userName},'%')

             AND userRole=#{userRole}

    </select>

方式三:传递的参数是Map集合 

Dao接口

    //根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是Map集合

    List<User> getUserListByNameAndRole3Map(Map<String,String> userMap);
Dao接口映射文件

    <!--根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是Map集合 #{map的Key}-->

    <select id="getUserListByNameAndRole3Map" resultType="user" parameterType="map">

        SELECT * FROM smbms_user WHERE userName LIKE CONCAT ('%',#{mapName},'%'

             AND userRole=#{mapRole}

    </select>

 

测试类



//根据用户名称和角色查询用户列表,用户名实现模糊查询  参数是Map集合


    @Test

    public void getUserListByNameAndRole3MapTest(){

        SqlSession sqlSession=null;

        Map<String,String> map=new HashMap<String,String>();

        map.put("mapName","赵");

        map.put("mapRole","3");

        try {

            //创建SqlSession实例

            sqlSession= MybatisUtil.createSqlSession();
            //创建UserMapper接口实例,调用其方法执行相关的SQL语句

            List<User> list = sqlSession.getMapper(UserMapper.class).getUserListByNameAndRole3Map(map);

            for (User user1:list){

                log.info("编码:" + user1.getUserCode()+"\t用户名:"+user1.getUserName()+"\t角色:"+user1.getUserRole());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }finally {

            MybatisUtil.closeSqlSession(sqlSession);

        }

    }

 

使用resultMap完成查询结果的展现 

多表联查是---->显示的并不是关联的id的值,而是相关联的表中某一列的值

有两种解决方案

1.修改实体类,增加userRoleName属性,并修改查询用户列表的SQL语句,对用户表和角色表进行连表查询,使用resultType做自动映射。

实体类

    private String userRoleName;//用户角色名称

    //生成对应的getter and setter 方法

Dao接口

    //多表联查 根据用户名称和角色查询用户列表  用户名实现模糊查询  参数是对象

    List<User> getUserListByNameAndRole(User user);
Dao接口映射文件

MyBatis中使用resultType做自动映射,一定要注意:字段名和实体的属性名必须保持一致。

若不一致,则需要给字段起别名,保证别名和属性名一致

    <!--多表联查 根据用户名称和角色查询用户列表  用户名实现模糊查询  参数是对象-->

    <select id="getUserListByNameAndRole" resultType="user" parameterType="user">

        SELECT u.*,r.`roleName` as userRoleName FROM `smbms_user` u,`smbms_role` r WHERE u.`userRole`=r.`id` AND u.`userName` LIKE  CONCAT ('%',#{userName},'%') AND u.`userRole`=#{userRole}
    </select>

2.通过resultMap来映射自定义结果 (常用)

resultMap元素的属性值和子节点

id属性:唯一标识,此id值用于select元素resultMap属性的引用

type属性:表示该resultMap的映射结果类型

result子节点:用于标识一些简单属性,其中

column属性表示从数据库中查询的字段名。

property属性表示查询出来的字段对应的值赋给实体对象的那个属性

    


实体类

    private String userRoleName;//用户角色名称

    //生成对应的getter and setter 方法

Dao接口


    //多表联查 根据用户名称和角色查询用户列表  用户名实现模糊查询  参数是对象

    List<User> getUserListByNameAndRole(User user);


 

Dao接口映射文件


    <!--多表联查 根据用户名称和角色查询用户列表  用户名实现模糊查询  参数是对象-->

    <select id="getUserListByNameAndRole" resultMap="userList" parameterType="user">

        SELECT u.*,r.`roleName` FROM `smbms_user` u,`smbms_role` r WHERE u.`userRole`=r.`id`

            AND u.`userName` LIKE  CONCAT ('%',#{userName},'%') AND u.`userRole`=#{userRole}

    </select>

    <resultMap id="userList" type="user">

        <result property="id" column="id"></result>

        <result property="userCode" column="userCode"></result>

        <result property="userName" column="userName"></result>

        <result property="userRoleName" column="roleName"></result>

    </resultMap>

使用resultMap实现高级结果映射

association [əˌsoʊsiˈeɪʃn]

复杂的关联类型,映射一个嵌套JavaBean属性;多对一 或 一对一

属性

property:用来映射查询结果子集的实体属性

javaType:完整Java类名或者别名

resultMap:引用外部resultMap

子元素

id

result


实体类 创建Role实体类,并在User实体类引入Role实体类

    private Role role;//用户角色

    //生成对应的getter and setter 方法



Dao接口


    //通过角色id获取相应的用户列表

    List<User> getUserListByRoleId(@Param("userRoleId")Integer id);



Dao接口映射文件  不做映射的字段是获取不到值的


    <!--通过角色id获取相应的用户列表-->
    <select id="getUserListByRoleId" parameterType="integer" resultMap="userRoleResult">
        SELECT u.*,r.`id` AS r_id,r.`roleCode`,r.`roleName` FROM `smbms_user` u,`smbms_role` r
        WHERE u.`userRole`=r.`id` AND u.`userRole`=#{userRoleId}
    </select>
    <resultMap id="userRoleResult" type="user">
        <result property="id" column="id"></result>
        <result property="userCode" column="userCode"></result>
        <result property="userName" column="userName"></result>
        <association property="role" javaType="Role">
            <id property="id" column="r_id"></id>
            <result property="roleCode" column="roleCode"></result>
            <result property="roleName" column="roleName"></result>
        </association>
    </resultMap>
或者=========================================================


    <!--通过角色id获取相应的用户列表-->
    <select id="getUserListByRoleId" parameterType="integer" resultMap="userRoleResult">
        SELECT u.*,r.`id` AS r_id,r.`roleCode`,r.`roleName` FROM `smbms_user` u,`smbms_role` r
        WHERE u.`userRole`=r.`id` AND u.`userRole`=#{userRoleId}
    </select>
    <resultMap id="userRoleResult" type="user">
        <result property="id" column="id"></result>
        <result property="userCode" column="userCode"></result>
        <result property="userName" column="userName"></result>
        <association property="role" javaType="Role" resultMap="roleResult">
            <id property="id" column="r_id"></id></association>
    </resultMap>
    <resultMap id="roleResult" type="role">
        <id property="id" column="r_id"></id>
        <result property="roleCode" column="roleCode"></result>
        <result property="roleName" column="roleName"></result>
    </resultMap>


collection

复杂类型集合,映射嵌套结果集到一个列表;一对多

属性

property:实体类中用来映射查询结果子集的集合属性

ofType:集合中元素的类型,完整Java类名或者别名

resultMap:引用外部resultMap

子元素

id

result

实体类 创建Address实体类,并在User实体类添加地址Address列表属性


    private List<Address> addressList;//用户地址列表

    //生成对应的getter and setter 方法
Dao接口

    //根据用户id   获取用户地址列表

    List<User> getAddressListByUserId(@Param("id")Integer userId);
Dao接口映射文件  不做映射的字段是获取不到值的

    <!--根据用户id   获取用户地址列表-->

    <select id="getAddressListByUserId" parameterType="integer" resultMap="userAddressResult">

        SELECT u.*,a.`id` AS a_id,a.`addressDesc`,a.contact,a.postCode,a.tel

        FROM `smbms_user` u,`smbms_address` a

        WHERE u.`id`=a.`userId` AND u.`id`=#{id}

    </select>

    <resultMap id="userAddressResult" type="user">

        <result property="id" column="id"></result>

        <result property="userCode" column="userCode"></result>

        <result property="userName" column="userName"></result>

        <collection property="addressList" ofType="address">

            <id property="id" column="a_id"/>

            <result property="postCode" column="postCode"/>

            <result property="tel" column="tel"/>

            <result property="contact" column="contact"/>

            <result property="addressDesc" column="addressDesc"/>
        </collection>
    </resultMap>


或者=========================================================


    <!--根据用户id   获取用户地址列表-->


    <select id="getAddressListByUserId" parameterType="integer" resultMap="userAddressResult">
        SELECT u.*,a.`id` AS a_id,a.`addressDesc`,a.contact,a.postCode,a.tel
        FROM `smbms_user` u,`smbms_address` a
        WHERE u.`id`=a.`userId` AND u.`id`=#{id}
    </select>
    <resultMap id="userAddressResult" type="user">
        <result property="id" column="id"></result>
        <result property="userCode" column="userCode"></result>
        <result property="userName" column="userName"></result>
        <collection property="addressList" ofType="address" resultMap="dizhi"></collection>
    </resultMap>
    <resultMap id="dizhi" type="address">
        <id property="id" column="a_id"/>
        <result property="postCode" column="postCode"/>
        <result property="tel" column="tel"/>
        <result property="contact" column="contact"/>
        <result property="addressDesc" column="addressDesc"/>
    </resultMap>

resultType与resultMap小结

自动映射的前提:属性名与字段名一致

自动映射级别:autoMappingBehavior

  <settings>

         <!-- 
         NONE:禁止自动匹配

         PARTIAL:自动匹配所有属性,内部嵌套除外

         FULL:自动匹配所有,包括内部嵌套(association、collection)

        -->

        <!-- 设置resultMap的自动映射级别为NONE (禁止自动匹配)   默认的为PARTIAL -->

        <setting name="autoMappingBehavior" value="FULL"/>

    </settings>

 

注:在MyBatis中,使用resultMap能够进行自动映射匹配的前提是字段名和属性名需要一致,在默认映射级别(PARTIAL)情况下,若一致,即使没有做属性名和字段名的匹配,也可以在后台取到未匹配过的属性值;若不一致,且在resultMap里没有做映射,那么就无法在后台获取并输出

1.Insert update delete 这类操作,本身默认就是返回影响的行数,所以不需要对resultType进行指定,只有查询类的操作,需要进行返回结果类型的指定

2.对于增删改这类更新操作,dao层接口方法的返回值为int类型,执行sql影响的行数。最好不要写boolean类型

注意:insert、update、delete元素均没有resultType/resultMap属性

使用MyBatis实现增操作-insert

insert元素的属性

id:与select元素的id一样,是命名空间唯一的标识符

parameterType:与select元素的parameterType一样,是传入参数的类型的完整类型名或别名

Dao接口


    //添加用户信息

    int add(User user);
Dao接口映射文件

    <!--添加用户信息-->

    <insert id="add" parameterType="user">

        INSERT INTO smbms_user (userCode,userName,userPassword,gender,birthday,

                    phone,address,userRole,createdBy,creationDate)

                VALUES (#{userCode},#{userName},#{userPassword},#{gender},#{birthday},

                #{phone},#{address},#{userRole},#{createdBy},#{creationDate})

    </insert>
测试类  模拟了事物



    //添加用户信息

    @Test
    public void addTest(){

        SqlSession sqlSession=null;

        int count=0;//记录影响的行数

        try {

            User user=new User();
            user.setUserCode("test001");
            user.setUserName("测试用户001");
            user.setUserPassword("1234567");
            Date birthday=new SimpleDateFormat("yyyy-MM-dd").parse("2020-11-14");
            user.setBirthday(birthday);
            user.setAddress("地址测试");
            user.setGender(1);
            user.setPhone("117600181675");
            user.setUserRole(1);

            user.setCreatedBy(1);

            user.setCreationDate(new Date());

            //创建SqlSession实例

            sqlSession= MybatisUtil.createSqlSession();

            //创建UserMapper接口实例,调用其方法执行相关的SQL语句

            count = sqlSession.getMapper(UserMapper.class).add(user);

            //模拟异常

            //int i=2/0;// by zero

            sqlSession.commit();

        } catch (Exception e) {

            e.printStackTrace();

            sqlSession.rollback();

            count=0;

        }finally {

            MybatisUtil.closeSqlSession(sqlSession);

        }

        log.info("addTest count:"+count);
    }

使用MyBatis实现改操作-update

update元素的属性

id:与select元素的id一样,是命名空间唯一的标识符

parameterType:与select元素的parameterType一样,是传入参数的类型的完整类型名或别名


Dao接口


    //修改用户信息

    int update(User user);

    //修改用户信息 根据id修改密码

    int updatePwd(@Param("id") Integer id,@Param("pwd") String pwd);


Dao接口映射文件


    <!--修改用户信息-->

    <update id="update" parameterType="user">

        UPDATE smbms_user SET userCode=#{userCode},userName=#{userName},

                    userPassword=#{userPassword},gender=#{gender},

                    birthday=#{birthday},phone=#{phone},

                    address=#{address},userRole=#{userRole},

                    modifyBy=#{modifyBy},modifyDate=#{modifyDate}

                WHERE id=#{id}

    </update>

    <!--修改用户信息 根据id修改密码-->

    <update id="updatePwd">

        UPDATE smbms_user SET userPassword=#{pwd}

                WHERE id=#{id}

    </update>

使用MyBatis实现删操作-delete

delete元素的属性

id:与select元素的id一样,是命名空间唯一的标识符

parameterType:与select元素的parameterType一样,是传入参数的类型的完整类型名或别名

Dao接口


    //删除用户信息  根据id


    int deleteUserById(@Param("id")Integer delId);
Dao接口映射文件


    <!--删除用户信息  根据id-->

    <delete id="deleteUserById" parameterType="integer">

        DELETE FROM smbms_user WHERE id=#{id}

    </delete>

MyBatis缓存

MyBatis提供了一级缓存和二级缓存

一级缓存缓存的是SQL语句,二级缓存缓存的是结果对象

一级缓存

一级缓存是基于PerpetualCache(MyBatis自带)的HashMap本地缓存,

默认开启,SqlSession级别的缓存。

作用范围为session域内。

执行过的SQL结果集默认放在缓存中,下一次执行直接从缓存中获取,

当session flush或者close之后,该session中所有的cache就会被清空。

二级缓存

二级缓存就是global caching(全局),它超出session范围之后(跨session的缓存),可以被所有SqlSession共享;默认是关闭的,SqlSessionFactory级别的。

开启它只需要在MyBatis的核心配置文件(mybatis-config.xml)中设置即可。

二级缓存的使用方式

1.MyBatis的全局cache配置,需在mybatis-config.xml的settings中设置

<settings>

    <setting name="cacheEnabled" value="true"/>
</settings>

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

<mapper namespace="com.msds.user.dao.UserMapper">

    <!-- 缓存配置 -->

    <cache eviction="FIFO" flushInterval="60000" 

        size="512" readOnly="true"/>

</mapper>

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

<select id="selectAll" resultType="Emp" useCache="true">

</select>

MyBatis缓存仅做简单了解,因为数据量达到一定程度时,内置的缓存机制将无法满足要求;MyBatis框架的核心是SQL管理;所以采用redis、MongoDB、OSCache等专业的缓存服务器会更加合理。