欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【MyBatis学习笔记】9:分别使用Map接口,@Param注解,JavaBean对象实现多参数传递

程序员文章站 2022-03-25 13:48:36
...

预备工作

书上把多参数传递放到了select元素那一块讲,不过这部分实际上增删查改都一样用。


新增一个用来测试的表:
【MyBatis学习笔记】9:分别使用Map接口,@Param注解,JavaBean对象实现多参数传递
Person类:

package model;

import enums.SexType;
import org.apache.ibatis.type.Alias;

@Alias("person")
public class Person {
    private Integer id;
    private String name;
    private SexType sexType;
    private String idCard;

    //getter和setter
}

在配置文件中注册枚举类型处理器:

    <!--注册类型处理器-->
    <typeHandlers>
        <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="enums.SexType"/>
    </typeHandlers>

如果缺少此处,那么使用@Param参数或JavaBean这种解放参数的方式配置解析枚举总是会报错。

映射文件:

<?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 namespace="mapper.PersonMapper">
    <!--到ResultSet的映射-->
    <resultMap id="personMap" type="person">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--性别用枚举整数下标从数据库获取-->
        <result column="sex_type" property="sexType" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
        <result column="id_card" property="idCard"/>
    </resultMap>

    <!--通过姓氏和性别查询出一些Person-->
    <!--这里会在后面使用不同的方式做到多参数传递-->
    <!--...-->

    <!--添加一个Person,性别用枚举整数下标存入数据库,顺便使用主键回填-->
    <insert id="addPerson" parameterType="person" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO person (name, sex_type, id_card)
        VALUES (#{name}, #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}, #{idCard})
    </insert>
</mapper>

Mapper接口:

package mapper;

import enums.SexType;
import model.Person;

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

public interface PersonMapper {
    //通过姓氏和性别查找人,可能查询到多个所以返回List<Person>
    //这里会在后面用不同的方式实现多参数传递
    //...

    //添加一个人
    int addPerson(Person person);
}

数据库表中添加的信息:
【MyBatis学习笔记】9:分别使用Map接口,@Param注解,JavaBean对象实现多参数传递

使用Map传递

将参数都放到Map里,然后把Map接口的实现类对象传递给方法。


映射器接口中添加:

    //通过姓氏和性别查找人,可能查询到多个所以返回List<Person>
    //使用Map传递多参数,参数可能有多种,但Map的value只能有一种,使用字符串是最合适的
    List<Person> findPersonByMap(Map<String, String> params);

映射文件中添加:

    <!--使用Map传递多参数,所以parameterType="map"-->
    <select id="findPersonByMap" parameterType="map" resultMap="personMap">
        SELECT
            id,
            name,
            sex_type,
            id_card
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
              AND sex_type = #{sexType}
    </select>

在主类中使用:

//调用工具类的静态方法开启并获取一个SqlSession实例
sqlSession = SqlSessionFactoryUtil.openSqlSession();
//获取映射器代理类对象
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);

//建立一个Map的实现类对象,按使用的参数名传入参数
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put("surname", "刘");
//枚举对象.ordinal()获取其下标整数,再用String.valueOf将其变成数字字符串
paramsMap.put("sexType", String.valueOf(SexType.MALE.ordinal()));
//查询,传入Map的实现类对象
List<Person> personList=personMapper.findPersonByMap(paramsMap);

//输出
for(Person p:personList){
    System.out.println(p.getId()+","+p.getIdCard()+","+p.getName()+","+p.getSexType());
}

//善后处理...

查询结果:
【MyBatis学习笔记】9:分别使用Map接口,@Param注解,JavaBean对象实现多参数传递


使用Map方式传递参数不是一个好的方法,原因有下:

  • 需要在使用处查看传入了什么参数,可读性下降,业务关联性差。
  • 传参时为了多种参数都合适,Map的Value总是使用String类型,还需类型转换比较麻烦。

使用@Param注解传递

这种方式能直接在方法签名上看到传递了什么参数,可读性是最好的。当参数不多(如不超过5),并且这些参数整体没有构成业务关联(即没有整个构成一个类)时,这种方式是最佳选择。


映射器接口中添加:

    //使用@Param("参数名")来传递参数
    List<Person> findPersonByAnnotation(@Param("surname") String surname, @Param("sexType") SexType sexType);

映射文件中添加:

    <!--使用注解传递参数,这时是不涉及单独一个类型的,所以去掉parameterType属性-->
    <!--必备的属性解析(如sex_type需要解析成整数下标)需要指明,因为参数不再全是String-->
    <select id="findPersonByAnnotation" resultMap="personMap">
        SELECT
            id,
            name,
            sex_type,
            id_card
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
              AND sex_type = #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>

在主类中使用:

//调用工具类的静态方法开启并获取一个SqlSession实例
sqlSession = SqlSessionFactoryUtil.openSqlSession();
//获取映射器代理类对象
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);

//直接传入参数查询,此时参数类型已经解放,不再必须是String
List<Person> personList = personMapper.findPersonByAnnotation("刘", SexType.MALE);

//输出和善后处理...

查询结果和前面一样。

使用JavaBean传递

当参数的数目比较多(如超过5个),或者参数之间的业务逻辑关联很强时,可以将参数整个到一个类的对象里,然后将整个对象传入。

这种方式牺牲了小部分可读性,但简化了代码,易于扩展和修改参数,并且业务逻辑性较强。


新增一个JavaBean类,其属性就是要传递的参数:

package param;

import enums.SexType;

public class MyParam {
    //注意配置文件中解析的属性名就是这里的名字,就像在值栈里一样
    private String surname;
    private SexType sexType;

    //getter和setter
}

映射器接口中添加:

    //使用JavaBean组合要传递的参数,传递JavaBean来传参
    List<Person> findPersonByJB(MyParam myParam);

映射文件中添加:

    <!--使用JavaBean来传递参数,这时parameterType=属性显然是这个JavaBean类-->
    <!--必备的属性解析(如sex_type需要解析成整数下标)需要指明,因为参数不再全是String-->
    <select id="findPersonByJB" parameterType="param.MyParam" resultMap="personMap">
        SELECT
            id,
            name,
            sex_type,
            id_card
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
              AND sex_type = #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>

在主类中使用:

//调用工具类的静态方法开启并获取一个SqlSession实例
sqlSession = SqlSessionFactoryUtil.openSqlSession();
//获取映射器代理类对象
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);

//建立这个参数的JavaBean对象
MyParam myParam=new MyParam();
myParam.setSurname("刘");
myParam.setSexType(SexType.MALE);
//传给这个查询方法,用于查询
List<Person> personList = personMapper.findPersonByJB(myParam);

//输出和善后处理...

查询结果和前面一样。