mybatis完成参数接收及结果集返回的多种方式(上)

116 阅读5分钟

一、前言 在使用Mybatis框架时,业务层会根据实际业务需求给Dao层传入参数,Dao层在根据传入的参数做了相关增删改查操作后会返回给业务层数据(从表中查询出的数据等)。

不管是接收参数还是返回结果集,Mybatis框架为了迎合多变的业务场景都给出了多种应对方案,下面将重点阐述这些方案。

二、Mybatis如何接收参数 方式一通过实体对象接收

在前几节的内容中,大部分的示例采用的都是这种方式,下面进行一个示例回顾。

Dao层接口UserMapper增加selectByPojo方法。

public User selectByPojo(User user); 可以发现Dao层的selectByPojo的参数类型是User类型,也就是通过实体对象接收参数。

映射文件UserMapper.xml中增加

select * from user where id = #{id} and username = #{username} and password = #{password} 测试方法如下
 @Test
public void test17() throws IOException {

    //1. 读取核心配置文件SqlMapConfig.xml
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2. 创建SqlSessionFactory工厂
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    //3. 使用工厂生产一个SqlSession对象
    SqlSession session = factory.openSession();
    //4. 使用SqlSession创建Dao接口的代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = new User(2, "lisi", "hello123");
    User userRes = userMapper.selectByPojo(user);
    System.out.println(userRes);
    //6. 释放资源
    session.close();
    in.close();
}

在测试方法中我们生成了id为2,username为lisi,password为hello123的对象。

再用Dao层userMapper调用selectByPojo方法,并将该对象作为参数传入。

UserMapper.xml对应的select标签用parameterType接收该实体对象并在SQL语句中采用#{对象属性值}的方式即#{id}、#{username}、#{password}读取user对象中的属性值。

这种方式是比较常见的参数接收方式,其可以将SQL语句所需的多个参数通过一个对象全部接收。

方式二通过多个参数接收

如上述通过实体对象接收参数,如果我是分别通过多个参数传入Dao层,Mybatis该如何获取参数呢?下面通过实例讲解。

Dao层接口UserMapper增加selectByPararms方法

public User selectByPararms(int id, String username, String password);

映射文件UserMapper.xml中增加

<select id="selectByPararms" resultType="com.zssj.domain.User">
        select * from user where id = #{id} and username = #{username} and password = #{password}
</select>

测试方法如下

@Test public void test18() throws IOException {

    //1. 读取核心配置文件SqlMapConfig.xml
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2. 创建SqlSessionFactory工厂
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    //3. 使用工厂生产一个SqlSession对象
    SqlSession session = factory.openSession();
    //4. 使用SqlSession创建Dao接口的代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User userRes = userMapper.selectByPararms(2,"lisi","hello123");
    System.out.println(userRes);

    //6. 释放资源
    session.close();
    in.close();
}

在测试方法中我们在用userMapper调用selectByPararms方法时传入的参数并没有封装到实体对象中传递过去,而是直接将对应的实参传递过去。此时我们运行测试方法发现报了如下错误。

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. `
 Available parameters are [arg2, arg1, arg0, param3, param1, param2]

这个报错显示没有找到id的值,也就是Dao层参数传递给UserMapper.xml的select标签时没有做好参数对应。

此时在多参数参与传递时要特别注意需要借助注解@Param,将Dao层接口UserMapper中selectByPararms每个参数都配有该注解就能正常执行了。

@Param()这个注解其实起到了类似于取别名的作用,这样mybatis就能根据这个注解将参数实现一一对应,不会出现多个参数但是值对应不上的情况。

方式三通过Map接收

Dao层接口UserMapper增加selectByMap方法

public User selectByMap(Map<String,Object> map); 映射文件UserMapper.xml中增加

<select id="selectByMap" resultType="com.zssj.domain.User">
      select * from user where id = #{id} and username = #{username} and password = #{password}
</select>

测试方法如下

@Test public void test19() throws IOException {

    //1. 读取核心配置文件SqlMapConfig.xml
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2. 创建SqlSessionFactory工厂
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    //3. 使用工厂生产一个SqlSession对象
    SqlSession session = factory.openSession();
    //4. 使用SqlSession创建Dao接口的代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("id",2);
    map.put("username", "lisi");
    map.put("password","hello123");
    User userRes = userMapper.selectByMap(map);
    System.out.println(userRes);
    //6. 释放资源
    session.close();
    in.close();
}

在测试方法中生成map并往里面塞值,key作为属性名,value是对应的值。

在UserMapper.xml对应的select标签中直接采用#{id}、#{username}、#{password}方式取出map中对应的值参与sql。

方式四#与$的区别

在上述示例中我们都采用#{属性名称}的方式获取变量值,除此之外也可以将#替换成$。

我们对通过Map接收这个示例的代码进行修改,将UserMapper.xm对应的selesct标签修改为使用$获取变量值。

<select id="selectByMap" resultType="com.zssj.domain.User">
                select * from user where
                 id = ${id} and username = ${username} and password = ${password}
    </select>

然后运行测试方法却发现报错

### The error may exist in com/zssj/mapper/UserMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select * from user where id = 2 and username = lisi and password = hello123
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
Unknown column 'lisi' in 'where clause'

通过分析错误展现的sql语句乍一看并没有错,但是我发现username对应的lisi和password对应的hello123本应该是字符串类型,这里并没有体现出来。

于是我改写了测试方法方法

@Test public void test19() throws IOException {

    //1. 读取核心配置文件SqlMapConfig.xml
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2. 创建SqlSessionFactory工厂
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    //3. 使用工厂生产一个SqlSession对象
    SqlSession session = factory.openSession();
    //4. 使用SqlSession创建Dao接口的代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("id",2);
    map.put("username", "'"+"lisi"+"'");
    map.put("password","'"+"hello123"+"'");
    User userRes = userMapper.selectByMap(map);
    System.out.println(userRes);
    //6. 释放资源
    session.close();
    in.close();
}

在测试方法中,将字符串类型的username和password对应的值都加上了单引号('')。此时再进行测试,就成功了。

究其原因使用$取值时其仅仅是采用字符串拼接的形式,这也是和#不同之处,#采用占位符的形式。

另外还要强调一点的是,取值还有个特殊的用处,如果sql语句中表名是变化的,那就只能用取值还有个特殊的用处,如果sql语句中表名是变化的,那就只能用取值。

除此之外,group by 字段 ,order by 字段,字段名等没法使用占位符的就需要使用${}形式。 ———————————————— 版权声明:本文为CSDN博主「你的知识书架」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/Bcoder_m/ar…