【web|mybatis】MyBatis 中的 Mapper 配置文件的参数引用

MyBatis 中的 Mapper 配置文件的参数引用

开源技术栏

Mapper 配置文件 中,SQL语句可以使用 #{} ${} 进行变量的引用,这个引用和 Mapper 接口的函数形参息息相关

目录


MyBatis

介绍

我们知道标题中提到的两种语法代表的就是变量赋值,但是,在占位符的大括号中,变量名应该是什么呢?
说到这里我们就需要了解下MyBatis 中的多种变量的引用方式

Mapper 中是单个参数

这种情况就是最简单的情况,Mapper接口中只有一个参数,下面就是Mapper接口的代码。

Mapper接口

package top.lingyuzhao.test.mapper;

import top.lingyuzhao.test.data.User;


/**
 * @author zhao
 */
public interface UserMapper {

    /**
     * 根据id查询用户
     *
     * @param id 用户id
     * @return 指定 id 对应的用户对象
     */
    User selectUserById(int id);
}

Mapper配置文件

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById 
     参数类型为 整形 代表要查询的数据的 id 
     返回值是一个 User 对象
     TODO 这个 selectUserById 只有一个参数
      变量的赋值方法就是 直接在大括号中写上 变量名 变量名需要与 selectUserById 函数中的形参一致-->
    <select id="selectUserById" parameterType="java.lang.Integer" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{id}
    </select>
</mapper>

MAIN 代码

package top.lingyuzhao.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.lingyuzhao.test.data.User;
import top.lingyuzhao.test.mapper.UserMapper;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author zhao
 */
public class Main {

    public static void main(String[] args) throws IOException {
        // 获取到核心配置文件
        final InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取 sql 会话的工厂构建对象
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 开始进行构建 在这里我们将配置文件的数据流传递给它 并调用 openSession 获取到会话对象
        final SqlSession sqlSession = sqlSessionFactoryBuilder
                .build(resourceAsStream)
                // TODO 这里需要传递一个 true 代表打开事务自动提交
                .openSession(true);

        // 获取到映射器对象 在这里将映射接口传递进去
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 查询到 id 为 2 的用户
        final User user = mapper.selectUserById(2);
        System.out.println(user);
    }
}

运行结果

2024-01-02 18:44:50,822 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==>  Preparing: SELECT * FROM t_user WHERE id = ?
2024-01-02 18:44:50,852 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==> Parameters: 2(Integer)
2024-01-02 18:44:50,867 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - <==      Total: 1
User{id=2, username='zhao123', password='0000', age=20, sex=男, email='xxx.@qq.com'}

进程已结束,退出代码0

Mapper 中是多个参数

在这里需要注意下,如果Mapper接口中的函数形参是多个,我们不能直接在大括号写变量名,不用纠结为什么,这是mybatis 的规则,接下来就有如何进行变量的引用。

Mapper接口

package top.lingyuzhao.test.mapper;

import top.lingyuzhao.test.data.User;


/**
 * @author zhao
 */
public interface UserMapper {

    /**
     * 根据id1 或者 id2 查询用户
     *
     * @param id1 用户id1
     * @param id2 用户id2
     * @return 指定 id 对应的用户对象
     */
    List<User> selectUserById(int id1, int id2);
}

MAIN代码

package top.lingyuzhao.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.lingyuzhao.test.data.User;
import top.lingyuzhao.test.mapper.UserMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author zhao
 */
public class Main {

    public static void main(String[] args) throws IOException {
        // 获取到核心配置文件
        final InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取 sql 会话的工厂构建对象
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 开始进行构建 在这里我们将配置文件的数据流传递给它 并调用 openSession 获取到会话对象
        final SqlSession sqlSession = sqlSessionFactoryBuilder
                .build(resourceAsStream)
                // TODO 这里需要传递一个 true 代表打开事务自动提交
                .openSession(true);

        // 获取到映射器对象 在这里将映射接口传递进去
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 查询到 id 为 1 or 2 的用户
        final List<User> user = mapper.selectUserById(1, 2);
        System.out.println(user);
    }
}

Mapper配置文件

在这里我们先按照 单个参数 的方法来直接赋值看看会发生什么吧!
错误示例

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById
     参数类型为 整形 代表要查询的数据的 id
     返回值是一个 User 对象
     TODO 这个 selectUserById 函数有两个参数
      变量的赋值方法就是 直接在大括号中写上 arg0 或者 arg1 
       也可以写 param0 或者 param1 都是可以的,这代表的就是函数的形参 
       0 结尾的是第一个形参,以此类推 -->
    <select id="selectUserById" parameterType="java.lang.Integer" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{id1} or id = #{id2}
    </select>
</mapper>

像上面这样配置 Mapper 会报错,报错内容如下所示,它在告知,你需要使用 arg0 arg1 param1 param2 的方法来代表第一个参数和第二个参数,其中,arg0 和 param1 代表函数第一个参数,后面的以此类推。

Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'id1' not found. Available parameters are [arg1, arg0, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id1' not found. Available parameters are [arg1, arg0, param1, param2]
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:153)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
	at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
	at com.sun.proxy.$Proxy4.selectUserById(Unknown Source)
	at top.lingyuzhao.test.Main.main(Main.java:31)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id1' not found. Available parameters are [arg1, arg0, param1, param2]
	at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212)
	at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)
	at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)
	at org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:219)
	at org.apache.ibatis.executor.CachingExecutor.createCacheKey(CachingExecutor.java:146)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:88)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
	... 8 more

正确示例

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById
     参数类型为 整形 代表要查询的数据的 id
     返回值是一个 User 对象
     TODO 这个 selectUserById 函数有两个参数
      变量的赋值方法就是 直接在大括号中写上 arg0 或者 arg1
       也可以写 param0 或者 param1 都是可以的,这代表的就是函数的形参
       0 结尾的是第一个形参,以此类推 -->
    <select id="selectUserById" parameterType="java.lang.Integer" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{param1} or id = #{param2}
    </select>
</mapper>

运行结果

下面就是运行结果,有关 MAIN 的代码可以在本节中的 Mapper接口 中查阅。

2024-01-02 18:55:00,352 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==>  Preparing: SELECT * FROM t_user WHERE id = ? or id = ?
2024-01-02 18:55:00,376 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==> Parameters: 1(Integer), 2(Integer)
2024-01-02 18:55:00,397 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - <==      Total: 2
[User{id=1, username='zhao', password='0000', age=21, sex=男, email='xxx.@qq.com'}, User{id=2, username='zhao123', password='0000', age=20, sex=男, email='xxx.@qq.com'}]

进程已结束,退出代码0

Mapper 中是一个 Map 集合

这其实就是一种多参数接收的变体,这样的方式可以实现参数名字的自定义,我们知道在上一节中,参数的名字都是 arg 以及 param 这两个 mybatis 中写死的名字,我们要是希望自定义参数名字 可以在这里学习到。
本质就是 Map 中的 key 就是变量名字 value 就是变量的具体数值,接下来开始学习。

Mapper接口

在这的形参变为了一个 Map 对象,下面就是 Mapper 接口的code。

package top.lingyuzhao.test.mapper;

import top.lingyuzhao.test.data.User;

import java.util.List;
import java.util.Map;


/**
 * @author zhao
 */
public interface UserMapper {

    /**
     * 根据 id 或者 username 查询用户
     * @param map 参数列表 其中 key 是参数名字 value 是参数数值
     * @return 指定 id 对应的用户对象
     */
    List<User> selectUserById(Map<String, Object> map);
}

Mapper配置文件

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById
     参数类型为 整形 代表要查询的数据的 id
     返回值是一个 User 对象
     TODO 这个 selectUserById 函数是一个 Map
       我们在这里就是读取Map中 key 为 id 以及 username 对应的值
       -->
    <select id="selectUserById" parameterType="java.util.Map" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{id} or username = #{username}
    </select>
</mapper>

MAIN 代码

package top.lingyuzhao.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.lingyuzhao.test.data.User;
import top.lingyuzhao.test.mapper.UserMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

/**
 * @author zhao
 */
public class Main {

    public static void main(String[] args) throws IOException {
        // 获取到核心配置文件
        final InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取 sql 会话的工厂构建对象
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 开始进行构建 在这里我们将配置文件的数据流传递给它 并调用 openSession 获取到会话对象
        final SqlSession sqlSession = sqlSessionFactoryBuilder
                .build(resourceAsStream)
                // TODO 这里需要传递一个 true 代表打开事务自动提交
                .openSession(true);

        // 获取到映射器对象 在这里将映射接口传递进去
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 准备参数 Map
        final HashMap<String, Object> hashMap = new HashMap<>();
        // 指定要查询的用户 id
        hashMap.put("id", 1);
        // 指定要查询的用户名字
        hashMap.put("username", "zhao123");
        // 开始进行查询
        final List<User> user = mapper.selectUserById(hashMap);
        System.out.println(user);
    }
}

运行结果

2024-01-02 19:06:16,154 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==>  Preparing: SELECT * FROM t_user WHERE id = ? or username = ?
2024-01-02 19:06:16,180 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==> Parameters: 1(Integer), zhao123(String)
2024-01-02 19:06:16,199 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - <==      Total: 2
[User{id=1, username='zhao', password='0000', age=21, sex=男, email='xxx.@qq.com'}, User{id=2, username='zhao123', password='0000', age=20, sex=男, email='xxx.@qq.com'}]

进程已结束,退出代码0

自定义Mapper中参数的名字

在 Mapper 中是多个参数的时候 参数名字是MyBatis 提供的,如果我们要是希望实现自定义名字,还需要自己构建一个 Map,这比较麻烦,所以我们可以直接使用注解的方式来针对参数进行重命名。

Mapper 接口

package top.lingyuzhao.test.mapper;

import org.apache.ibatis.annotations.Param;
import top.lingyuzhao.test.data.User;

import java.util.List;


/**
 * @author zhao
 */
public interface UserMapper {

    /**
     * 根据id1 或者 id2 查询用户
     *
     * @param id1 用户id1
     * @param id2 用户id2
     * @return 指定 id 对应的用户对象
     */
    List<User> selectUserById(@Param("id_1") int id1, @Param("id_2") int id2);
}

Mapper配置文件

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById
     参数类型为 整形 代表要查询的数据的 id
     返回值是一个 User 对象
     TODO 这个 selectUserById 函数有两个参数
      分别被我们使用注解命名为了 id_1 id_2 -->
    <select id="selectUserById" parameterType="top.lingyuzhao.test.data.User" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{id_1}
           or id = #{id_2}
    </select>
</mapper>

MAIN 代码

package top.lingyuzhao.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.lingyuzhao.test.data.User;
import top.lingyuzhao.test.mapper.UserMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author zhao
 */
public class Main {

    public static void main(String[] args) throws IOException {
        // 获取到核心配置文件
        final InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取 sql 会话的工厂构建对象
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 开始进行构建 在这里我们将配置文件的数据流传递给它 并调用 openSession 获取到会话对象
        final SqlSession sqlSession = sqlSessionFactoryBuilder
                .build(resourceAsStream)
                // TODO 这里需要传递一个 true 代表打开事务自动提交
                .openSession(true);

        // 获取到映射器对象 在这里将映射接口传递进去
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 开始进行查询
        final List<User> user = mapper.selectUserById(1, 2);
        System.out.println(user);
    }
}

运行结果

2024-01-02 19:23:34,084 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==>  Preparing: SELECT * FROM t_user WHERE id = ? or id = ?
2024-01-02 19:23:34,100 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==> Parameters: 1(Integer), 2(Integer)
2024-01-02 19:23:34,115 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - <==      Total: 2
[User{id=1, username='zhao', password='0000', age=21, sex=男, email='xxx.@qq.com'}, User{id=2, username='zhao123', password='0000', age=20, sex=男, email='xxx.@qq.com'}]

进程已结束,退出代码0

Mapper 中是一个 实体类

在 myBatis 中 我们的Mapper接口也可以是一个实体类,这个就是很常用的一种手段,所以我们先来创建一个存储数据的实体类。

创建实体类型

package top.lingyuzhao.test.data;

/**
 * @author zhao
 */
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Character sex;
    private String email;

    public User(Integer id, String username, String password, Integer age, Character sex, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", email='" + email + '\'' +
                '}';
    }
}

Mapper接口

package top.lingyuzhao.test.mapper;

import top.lingyuzhao.test.data.User;

import java.util.List;


/**
 * @author zhao
 */
public interface UserMapper {

    /**
     * 根据 id 或者 username 查询用户
     * @param user 用户数据参数 其中具有 id 和 username 字段
     * @return 指定 id 对应的用户对象
     */
    List<User> selectUserById(User user);
}

Mapper配置文件

<?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 接口 -->
<mapper namespace="top.lingyuzhao.test.mapper.UserMapper">
    <!--
     函数名称为 selectUserById
     参数类型为 整形 代表要查询的数据的 id
     返回值是一个 User 对象
     TODO 这个 selectUserById 函数形参是一个 User 对象
       我们在这里就是读取 User 中 属性 为 id 以及 username 对应的值
       -->
    <select id="selectUserById" parameterType="top.lingyuzhao.test.data.User" resultType="User">
        SELECT *
        FROM t_user
        WHERE id = #{id}
           or username = #{username}
    </select>
</mapper>

MAIN 代码

package top.lingyuzhao.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.lingyuzhao.test.data.User;
import top.lingyuzhao.test.mapper.UserMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author zhao
 */
public class Main {

    public static void main(String[] args) throws IOException {
        // 获取到核心配置文件
        final InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取 sql 会话的工厂构建对象
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 开始进行构建 在这里我们将配置文件的数据流传递给它 并调用 openSession 获取到会话对象
        final SqlSession sqlSession = sqlSessionFactoryBuilder
                .build(resourceAsStream)
                // TODO 这里需要传递一个 true 代表打开事务自动提交
                .openSession(true);

        // 获取到映射器对象 在这里将映射接口传递进去
        final UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 准备参数
        final User userObj = new User(
                // 指定要查询的用户 id
                1,
                // 指定要查询的用户名字
                "zhao123",
                // 其它参数用不上
                null, null, null, null
        );
        // 开始进行查询
        final List<User> user = mapper.selectUserById(userObj);
        System.out.println(user);
    }
}

运行结果

2024-01-02 19:17:02,743 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==>  Preparing: SELECT * FROM t_user WHERE id = ? or username = ?
2024-01-02 19:17:02,766 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - ==> Parameters: 1(Integer), zhao123(String)
2024-01-02 19:17:02,782 [main] DEBUG [top.lingyuzhao.test.mapper.UserMapper.selectUserById] - <==      Total: 2
[User{id=1, username='zhao', password='0000', age=21, sex=男, email='xxx.@qq.com'}, User{id=2, username='zhao123', password='0000', age=20, sex=男, email='xxx.@qq.com'}]

进程已结束,退出代码0

操作记录
作者:root
操作时间:2024-01-08 08:54:20 星期一
事件描述备注:保存/发布


PS:在这里的文章内容不全,您可以访问下面的链接,继续阅读,因为字太多啦,重新写一遍有点累累的!
http://www.lingyuzhao.top/?/linkController=/articleController&link=-39773805

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值