【MyBatis学习笔记】10:#和$,sql元素,resultMap的结构/构造器,存储结果集

#和$

在MyBatis的SQL中使用#{}${}都会被视为特殊字符串来处理。前者是设置了参数,MyBatis会将参数设置到语句中(默认是PreparedStatement)。后者是传递特殊字符串所对应的变量值,而不是传递参数。


修改上篇中@Param传递多参数的例子。

为映射器接口中的方法添加一个参数:

List<Person> findPersonByAnnotation(@Param("columns") String columns,@Param("surname") String surname, @Param("sexType") SexType sexType);

修改相应的映射配置,将使用${}将这个参数变成直出的变量:

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

在主类中使用查询:

List<Person> personList = personMapper.findPersonByAnnotation("id,name","刘",SexType.MALE);

查询结果:
这里写图片描述
只查询了这两列,所以其它属性是空。

映射配置中的sql元素

基本使用

映射配置中的sql元素用于定义一串SQL语句的组成部分,其它的语句可以通过引用来使用它。


如要实现和前面一样的功能,可以不从参数传入${},而是配置到sql元素中解耦:

    <sql id="columns">
        id,name
    </sql>
    <select id="findPersonByAnnotation" resultMap="personMap">
        SELECT <include refid="columns"/>
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
              AND sex_type = #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>

这里<include refid="sql元素的id"/>即是将这部分SQL代码原封不动的引用到了相应位置上。

向sql元素中传参

可以在include元素内配置property子元素,向sql元素中传递参数,再将转化${参数名}为相应参数值后的SQL引入该位置。


还是相同的功能,若将表名作为参数传入:

    <sql id="columns">
        ${prefix}.id, ${prefix}.name
    </sql>
    <select id="findPersonByAnnotation" resultMap="personMap">
        SELECT
        <include refid="columns">
            <!--设置sql元素中的${prefix}的参数值为person(表名)-->
            <property name="prefix" value="person"/>
        </include>
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
        AND sex_type = #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>

resultMap元素结构

<!--结果集映射-->
<resultMap id="" type="">
    <!--配置构造方法-->
    <constructor>
        <idArg column="" javaType=""/>
        <arg column="" javaType=""/>
    </constructor>
    <!--主属性-->
    <id property="" column=""/>
    <!--非主属性-->
    <result property="" column=""/>
    <!--一对一关系-->
    <association property="" column="" select=""/>
    <!--一对多关系-->
    <collection property="" column="" select=""/>
    <!--鉴别器-->
    <discriminator javaType="" column="">
        <case value="" resultMap=""/>
    </discriminator>
</resultMap>

constructor子元素

使用resultMapconstructor子元素来配置一个POJO的构造器,因为POJO类不见得会有无参构造方法。可以认为后面的idresult子元素对应的是setter方法传参,而这个子元素则是用构造方法来传参构造POJO对象的。

使用constructor元素时,里面的idArg子元素表示主属性,arg子元素则是非主属性,使用方法和idresult元素类似。

存储结果集

使用POJO存储结果集

前面学习的一直是这种方式,只要select元素配置了resultMap属性指向一个结果映射,或者使用resultType属性指向一个POJO类或其别名,那么Mapper接口的相应方法就应当设计成返回一个POJO对象的形式。

使用Map存储结果集

就像使用Map可以做多参数传递一样,结果集也是多个参数的集合,可以全部存在Map里面。使用resultType="map",那么Mapper接口的相应方法就应当设计成返回一个Map接口的实现类对象的形式。


映射文件中添加:

    <!--使用Map存储结果集,所以resultType="map"-->
    <select id="findToMap" resultType="map">
        SELECT *
        FROM person
        WHERE name LIKE CONCAT(#{surname}, '%')
              AND sex_type = #{sexType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    </select>

映射器接口中添加相应的方法:

List<HashMap<String,String>> findToMap(@Param("surname") String surname, @Param("sexType") SexType sexType);

主类中使用,获取到一个存Map实现类的List,然后遍历,以数据库中的列名(而不是POJO属性名)为key获取结果集各个列的值:

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

//传给这个查询方法,用于查询
List<HashMap<String,String>> mapList = personMapper.findToMap("刘",SexType.MALE);
//输出,注意以数据库中的列名(而不是POJO属性名)为key
for (HashMap p:mapList) {
    System.out.println(p.get("id")+","+p.get("name")+","+p.get("sex_type")+","+p.get("id_card"));
}

//善后处理...

运行结果:
这里写图片描述
从第三列是1可以看出,这种方式的一大特点即在于,数据库中存的是什么,查出来的就是什么样的字符串。在多数时候,这样可能会失去语义(如1本来应代表枚举MALE),而且使用这种方式会让可读性下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值