Mybatis XML映射文件:查询元素解析+案例+个人玩转参数问题案例详解

🕊前言

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

下面介绍的都是元素比较常用的属性,如若想要了解更多属性,欢迎点击Mybatis3中文官方文档
以下所有的解析使用的数据库表为user表,以下为数据:

在这里插入图片描述

🕊查询元素select

常用的属性

id在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常!
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。

案例

1、查询所有用户
UserMapper接口

//    查询所有用户
    List<User> getUserList();

UserMapper.xml

    <select id="getUserList" resultType="com.xmonster.pojo.User">
        select * from mybatis.user
    </select>

注意返回值的类型写法

2、根据id查询某用户

UserMapper接口

//    根据id查询某用户
    User getUserId(int id);

UserMapper.xml

    <select id="getUserId" parameterType="int" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where id=#{id}
    </select>

3、模糊查询
注意:Java代码执行的时候,传递通配符%
UserMapper接口

//    模糊查询
    List<User> getUserLike(String value);

UserMapper.xml

    <select id="getUserLike" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name like "%"#{value}"%";
    </select>

🕊insert, update 和 delete

参数

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。 在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常!
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
useGeneratedKeys(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

案例

UserMapper.java

//    插入用户
    int addUser(User user);
//    万能的map插入
    int addUser2(Map<String, Object> map);
//    更新用户
    int updateUser(User user);
//    万能map修改用户密码
    int updateUser2(Map<String, Object> map);
//    删除用户
    int deleteUser(int id);

UserMapper.xml

  <insert id="addUser" parameterType="com.xmonster.pojo.User" >
        insert into mybatis.user (id,name ,pwd) values (#{id}, #{name}, #{pwd})
    </insert>
    
<!--    万能map,values后面的#{},括号里的值可以不用和User对象的属性名一一对应,反正传递的时map的key值-->
    <insert id="addUser2" parameterType="map" >
        insert into mybatis.user (id,name ,pwd) values (#{userId}, #{userName}, #{Password})
    </insert>

    <update id="updateUser" parameterType="com.xmonster.pojo.User">
        update mybatis.user set name=#{name}, pwd=#{pwd} where id=#{id}
    </update>

<!--    万能map修改用户密码-->
    <update id="updateUser2" parameterType="map">
        update mybatis.user set pwd=#{Password} where id=#{userId}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>

test.java

//add
    @Test
    public void test1(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        int blue = mapper.addUser(new User(4, "blue", "19334"));
        sqlSession.commit();
        sqlSession.close();
    }
//map 插入
    @Test
    public void test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        Map<String, Object> map = new HashMap<>();
        map.put("userId", 4);
        map.put("userName", "aa");
        map.put("Password", "444444");
        mapper.addUser2(map);
        sqlSession.commit();
        sqlSession.close();
    }
 //更新
    @Test
    public void test3(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.updateUser(new User(4,"red","222222"));
        sqlSession.commit();
        sqlSession.close();
    }
 //map指定元素更新    
     @Test
    public void test4(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        Map<String, Object> map = new HashMap<>();
        map.put("userId", 4);
        map.put("Password", "333333");
        mapper.updateUser2(map);
        sqlSession.commit();
        sqlSession.close();
    }
 //删除用户
       @Test
    public void test5(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.deleteUser(4);
        sqlSession.commit();
        sqlSession.close();
    }

注意点

每次使用增删改查之后,不要忘记提交事务:sqlSession.commit();
也可以选择在(一般放在工具类里)MybatisUtils里,也就是生成sqlsession的函数中,在执行返回值的时候,参数选择true,这样每次你执行的时候都会自动提交事务:

public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }

🕊sql元素

对重复的sql语句进行组装起来,使用SQL标签抽取公共部分,在需要使用的地方include即可。下面是个例子,没有任何前后逻辑,就是单纯的例子:
Mapper.xml:

    <sql id="if-title-author">
        <if test="title != null">
            and title=#{title}
        </if>
        <if test="author != null">
            and author=#{author}
        </if>
    </sql>
<!--    查询博客-->
    <select id="queryBolg" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
         <include refid="if-title-author"></include>
        </where>
    </select>

用标签引入,refid填sql片段的id即可
抽取的原则

  1. 最好基于单表来定义SQL片段!
  2. 不要存在where标签,把where丢进去就没啥用了,去想想什么才叫复用

🕊参数

MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap,这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。

情景一:省略parameterType(无注解情况)

传入的参数是简单的int类型,就比如上面的根据id查询用户信息,其实我也可以不用写parameterType,系统会自动的进行匹配,甚至在Mapper.xml里#{}括号里的参数也可以和接口参数名字不一致,

下面是针对输入一个参数的测试

Mapper.xml:

    <select id="getUserId" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where id=#{uid}
    </select>

在这里插入图片描述
上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名
但是这里只是针对这种非常简单的情况,这里的简单是指首先查询语句简单,其次就是传递的参数很简单,但是原始类型简单数据类型(比如 Integer 和 String)因为没有其它属性,会用它们的值来作为参数。
再来一次测试
需求:输入用户的名字,输出对应用户的所有信息
UserMapper接口

//    根据输入用户的名字输出对应用户信息
    User getUserName(String name);

UserMapper.xml

    <select id="getUserName" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name=#{uname}
    </select>

在这里插入图片描述
但是为了规范,#{}括号里的参数最好和接口参数名称一致,就不要向上面一样又是id,又是uid

输入两个参数

这里就有要注意的点了,先来看一下代码
UserMapper接口

//    根据输入的用户姓名和密码查找对应的用户信息
    User getUserByNamePwd(String name, String pwd);

UserMapper.xml

    <select id="getUserByNamePwd" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name=#{name} and pwd=#{pwd};
    </select>

test.java

    @Test
    public void test9(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        User userId = mapper.getUserByNamePwd("xmonster","123456");
        System.out.println(userId);
        sqlSession.close();
    }

结果发现报错:
在这里插入图片描述

顺序映射方式(不使用注解和map)

原因:在Mybatis中当映射器需要多个参数的时候,有三种方法,一种是需要是需要导包的,这里与其说是要导包不如说是要用注解来解决问题;还有map;还有一种就是使用它默认的参数,这也就是顺序映射方式
我们只需要改变XML配置当中的参数即可,但是我们一般如果说是多参数,又不想用注解,又不想用map,就是想要单纯的两个参数来达到目的的话,一般这几个参数的参数类型都是同一个类型
就如果说你想通过id和name去查用户信息,id和name一个是int,一个是String,那么你的parameterType就不好写,简单来说也没人会这么用,除非这几个参数是同一个类型,或者你传入的参数是一个对象,不过在输入的时候你就要三个属性都输入,显然这和我只想要输入两个参数的目的不符
举个例子,想要通过输入用户名字和密码查询该用户所有信息,就只输入两个参数,不输入id的情况
UserMapper接口

//    输入用户id和名字,输出对应的用户的信息
    User getUserNamePwd(String name, String Pwd);

UserMapper.xml

    <select id="getUserNamePwd" parameterType="String" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name =#{param1} and pwd=#{param2}
    </select>

test.java

    @Test
    public void test9(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        User user = mapper.getUserNamePwd("xmonster", "123456");
        System.out.println(user);
        sqlSession.close();
    }

测试发现通过:
在这里插入图片描述

小结

顺序映射方法其实使用的情况比较少,可以看到在Mapper.xml中参数用的是param1 param2这也和上面的报错信息一致,旧版本的Mybatis用的是#{0} #{1}进行映射的

情景二:使用注解

先解决一下上面的问题
直接修改
UserMapper接口

//    根据输入的用户姓名和密码查找对应的用户信息
    User getUserByNamePwd(@Param("id") int id, @Param("name") String name, @Param("pwd") String pwd);

其他不变,可以看到,我们成功查出
在这里插入图片描述
当然了使用注解就可以不用管多少个参数了,参数类型一不一致了,在传参的时候Mapper.xml文件中#{}括号里写入的参数是@Param里的,而不是你自己定义的参数名字
比如

//    根据输入的用户姓名和密码查找对应的用户信息
User getUserByNamePwd(@Param("uid") int id, @Param("uname") String name, @Param("upwd") String pwd);

那么在Mapper.xml中就只认得uid/uname/upwd,传参时注意

小结

关于@param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不用加
  • 如果只有一个基本类型,可以忽略,但是建议大家都加上!
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名!

使用map

使用ma直接看上方案例即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是X大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值