Mybatis学习(4)输入映射、输出映射、动态sql

一、输入映射:

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型

1) 传递pojo的包装对象

需求是:完成用户信息的综合查询,传入的查询条件复杂;(包括用户信息、其他信息等);

定义包装类型:

  用户扩展类:

package com.cy.po;

/**
 *用户的扩展类
 * @author chengyu
 *
 */
public class UserCustom extends User{

}

  视图层面的用户包装类型:

 1 package com.cy.po;
 2
 3 /**
 4  * 用户的包装类型
 5  * @author chengyu
 6  *
 7  */
 8 public class UserQueryVo {
 9     //在这里包装所需要的查询条件
10
11     //用户查询条件
12     private UserCustom userCustom;
13
14     //可以包装其它的查询条件,订单、商品
15     //....
16
17     public UserCustom getUserCustom() {
18         return userCustom;
19     }
20
21     public void setUserCustom(UserCustom userCustom) {
22         this.userCustom = userCustom;
23     }
24 }

mapper.xml:

<!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo包装对象中用户名称
     -->
    <select id="findUserList" parameterType="com.cy.po.UserQueryVo" resultType="com.cy.po.UserCustom">
        SELECT * FROM USER where sex = #{userCustom.sex} and username like ‘%${userCustom.username}%‘
    </select>

mapper.接口:

public interface UserMapper {
    //用户信息综合查询
    public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;

测试代码:

 1 @Test
 2     public void testFindUserList() throws Exception {
 3         SqlSession sqlSession = sqlSessionFactory.openSession();
 4         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 5
 6         //创建包装对象,设置查询条件
 7         UserQueryVo userQueryVo = new UserQueryVo();
 8         UserCustom userCustom = new UserCustom();
 9         userCustom.setSex("1");
10         userCustom.setUsername("张三丰");
11         userQueryVo.setUserCustom(userCustom);
12         //调用userMapper的方法
13
14         List<UserCustom> list = userMapper.findUserList(userQueryVo);
15
16         System.out.println(list);
17     }

二、输出映射、

1、resultType:

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。

只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

1)  输出简单类型: ----》》查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

需求是,用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。

mapper.xml:

1 <!-- 用户信息综合查询总数
2     parameterType:指定输入类型和findUserList一样
3     resultType:输出结果类型
4      -->
5     <select id="findUserCount" parameterType="com.cy.po.UserQueryVo" resultType="int">
6        SELECT count(*) FROM USER  where sex = #{userCustom.sex} and username like ‘%${userCustom.username}%‘
7     </select>

mapper.java接口:

//用户信息综合查询总数
    public int findUserCount(UserQueryVo userQueryVo) throws Exception;

juit测试代码:

 1 //测试查询用户数
 2     @Test
 3     public void testFindUserCount() throws Exception {
 4         SqlSession sqlSession = sqlSessionFactory.openSession();
 5         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 6
 7         //创建包装对象,设置查询条件
 8         UserQueryVo userQueryVo = new UserQueryVo();
 9         UserCustom userCustom = new UserCustom();
10         userCustom.setSex("1");
11         userCustom.setUsername("张三丰");
12         userQueryVo.setUserCustom(userCustom);
13         int count = userMapper.findUserCount(userQueryVo);
14         System.out.println(count);
15     }

2)输出pojo对象,和pojo对象列表:

不管是输出的pojo单个对象还是一个列表,在mapper.xml中resultType指定的类型是一样的。在mapper.java指定的方法返回值类型不一样;

输出单个pojo,返回值是这个pojo对象类型

输出pojo列表,返回值是List<pojo>

2.resultMap

mybatis中使用resultMap完成高级输出结果映射。如果查询出来的列名和pojo的属性名不一致,可以通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

使用方法啊:

1)定义resultMap

2)使用resultMap作为statement的输出映射类型

mapper.xml:

 1 <!--使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址-->
 2 <mapper namespace="com.cy.mapper.UserMapper">
 3
 4     <!-- 定义resultMap 将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系
 5     type:resultMap最终映射的java对象类型,可以使用别名
 6     id:对resultMap的唯一标识
 7      -->
 8      <resultMap type="com.cy.po.User" id="userResultMap">
 9          <!-- id表示查询结果集中唯一标识  column:查询出来的列名 property:type指定的pojo类型中的属性名-->
10          <id column="id_" property="id"/>
11
12          <!-- result:对普通名映射定义 column:查询出来的列名 property:type指定的pojo类型中的属性名 -->
13          <result column="username_" property="username"/>
14      </resultMap>
15
16      <!-- 使用resultMap进行输出映射
17     resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
18     -->
19     <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
20         SELECT id id_,username username_ FROM USER WHERE id=#{value}
21     </select>
22 </mapper>

mapper接口:

//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;

juittest代码:

@Test
    public void testFindUserByIdResultMap() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user = userMapper.findUserByIdResultMap(1);
        System.out.println(user);
    }

3.自己做的实验,输入类型和传出类型都为java.util.Map:

<!-- 查看resultMap的使用 java.util.Map
        传入参数为hashmap id和username都为map的key
    -->
    <select id="findUserByIdDefaultMap" parameterType="java.util.Map" resultType="java.util.Map">
        SELECT * FROM USER where id=#{id} and username like ‘%${username}%‘
    </select>

并且java.util.Map在mybatis中的别名是hashmap,写成这样,效果一样的:

<select id="findUserByIdDefaultMap" parameterType="hashmap" resultType="hashmap">
        SELECT * FROM USER where id=#{id} and username like ‘%${username}%‘
    </select>

mapper接口:

//find user parameterMap and resultMap both are java.uti.Map
public Map<String, String> findUserByIdDefaultMap(Map<String, String> parmas) throws Exception;

测试代码:

@Test
    public void testfindUserByIdDefaultMap() throws Exception{
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        Map<String ,String> params = new HashMap<String, String>();
        params.put("id", "25");
        params.put("username", "小明");
        Map<String, String> user = userMapper.findUserByIdDefaultMap(params);
        System.out.println(user);
    }

打印结果:

DEBUG [main] - ==>  Preparing: SELECT * FROM USER where id=? and username like ‘%小明%‘
DEBUG [main] - ==> Parameters: 25(String)
DEBUG [main] - <==      Total: 1
{id=25, sex=1, username=陈小明, address=河南郑州}

  

三、动态sql

mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。

例子1:

  需求: 对上面程序中的  用户信息综合查询列表这个statement使用动态sql,对查询条件进行判断,如果输入参数不为空才进行查询条件拼接。

mapper.xml:

<!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo包装对象中用户名称
     -->
    <select id="findUserList" parameterType="com.cy.po.UserQueryVo" resultType="com.cy.po.UserCustom">
        SELECT * FROM USER

        <!-- where可以自动去掉条件中的第一个and -->
        <where>
            <if test="userCustom!=null">
                <if test="userCustom.sex!=null and userCustom.sex!=‘‘">
                    and sex = #{userCustom.sex}
                </if>
                <if test="userCustom.username!=null and userCustom.username!=‘‘">
                    and username like ‘%${userCustom.username}%‘
                </if>
            </if>
        </where>
    </select>

测试代码:

 1 @Test
 2     public void testFindUserList() throws Exception {
 3         SqlSession sqlSession = sqlSessionFactory.openSession();
 4         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 5
 6         //创建包装对象,设置查询条件
 7         UserQueryVo userQueryVo = new UserQueryVo();
 8         UserCustom userCustom = new UserCustom();
 9
10         //动态sql的存在,不设置某个值,条件不会拼接在sql中
11         //userCustom.setSex("1");
12         userCustom.setUsername("小明");
13         userQueryVo.setUserCustom(userCustom);
14
15         List<UserCustom> list = userMapper.findUserList(userQueryVo);
16         System.out.println(list);
17     }

打印:

DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE username like ‘%小明%‘
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 3
[------->> User [id=16, username=张小明, sex=1, birthday=null, address=河南郑州], ------->> User [id=22, username=陈小明, sex=1, birthday=null, address=河南郑州], ------->> User [id=25, username=陈小明, sex=1, birthday=null, address=河南郑州]]

2)sql片段:

将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。

mapper.xml:----定义sql片段、引用sql片段:

<mapper namespace="com.cy.mapper.UserMapper">

    <!-- 定义sql片段id:sql片段的唯 一标识
         经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高;在sql片段中不要包括 where
    -->
    <sql id="query_user_where">
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=‘‘">
                and sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=‘‘">
                and username like ‘%${userCustom.username}%‘
            </if>
        </if>
    </sql>

    <!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo包装对象中用户名称
     -->
    <select id="findUserList" parameterType="com.cy.po.UserQueryVo" resultType="com.cy.po.UserCustom">
        SELECT * FROM USER
        <where>
            <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->
            <include refid="query_user_where"></include>
        </where>
    </select>
</mapper>

3)使用foreach标签:

向sql传递数组或List,mybatis使用foreach解析;

需求:在用户查询列表的statement中增加多个id输入查询。

输入参数类型UserQueryVo中添加ids List,根据这个list查:

 1 package com.cy.po;
 2
 3 import java.util.List;
 4
 5 /**
 6  * 用户的包装类型
 7  * @author chengyu
 8  *
 9  */
10 public class UserQueryVo {
11     //在这里包装所需要的查询条件
12
13     private List<Integer> ids;
14
15     //用户查询条件
16     private UserCustom userCustom;
17
18     //可以包装其它的查询条件,订单、商品
19     //....
20
21     public List<Integer> getIds() {
22         return ids;
23     }
24     public void setIds(List<Integer> ids) {
25         this.ids = ids;
26     }
27     public UserCustom getUserCustom() {
28         return userCustom;
29     }
30     public void setUserCustom(UserCustom userCustom) {
31         this.userCustom = userCustom;
32     }
33 }

mapper.xml:

    <sql id="query_user_where">
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=‘‘">
                and sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=‘‘">
                and username like ‘%${userCustom.username}%‘
            </if>
            <if test="ids!=null">
                <!-- 使用 foreach遍历传入ids
                collection:指定输入 对象中集合属性
                item:每个遍历生成对象中
                open:开始遍历时拼接的串
                close:结束遍历时拼接的串
                separator:遍历的两个对象中需要拼接的串
                 -->

                <!-- AND (id=1 OR id=10 OR id=16)-->
                <foreach collection="ids" item="user_id" open="and (" close=")" separator="or">
                    id=#{user_id}
                </foreach>

                <!-- and id IN(1,10,16) -->
                <!-- <foreach collection="ids" item="user_id" open="and id in(" close=")" separator=",">
                    #{user_id}
                </foreach> -->
            </if>
        </if>
    </sql>

    <!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo包装对象中用户名称
     -->
    <select id="findUserList" parameterType="com.cy.po.UserQueryVo" resultType="com.cy.po.UserCustom">
        SELECT * FROM USER
        <where>
            <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->
            <include refid="query_user_where"></include>
        </where>
    </select>

测试代码:

 1 @Test
 2     public void testFindUserList() throws Exception {
 3         SqlSession sqlSession = sqlSessionFactory.openSession();
 4         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 5
 6         //创建包装对象,设置查询条件
 7         UserQueryVo userQueryVo = new UserQueryVo();
 8         UserCustom userCustom = new UserCustom();
 9
10         //动态sql的存在,不设置某个值,条件不会拼接在sql中
11         //userCustom.setSex("1");
12         userCustom.setUsername("小明");
13
14         //传入多个id
15         List<Integer> ids = new ArrayList<Integer>();
16         ids.add(1);
17         ids.add(10);
18         ids.add(16);
19         userQueryVo.setIds(ids);
20         userQueryVo.setUserCustom(userCustom);
21
22         List<UserCustom> list = userMapper.findUserList(userQueryVo);
23         System.out.println(list);
24     }

可以看打印结果拼接的sql:

DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE username like ‘%小明%‘ and ( id=? or id=? or id=? )
DEBUG [main] - ==> Parameters: 1(Integer), 10(Integer), 16(Integer)
DEBUG [main] - <== Total: 1
[------->> User [id=16, username=张小明, sex=1, birthday=null, address=河南郑州]]

时间: 2024-10-31 15:00:53

Mybatis学习(4)输入映射、输出映射、动态sql的相关文章

MyBatis总结之输入和输出映射

我们知道mybatis中输入映射和输出映射可以是基本数据类型.hashmap或者pojo的包装类型,这里主要来总结一下pojo包装类型的使用,因为这个在开发中比较常用. 1. 输入映射 输入映射,是在映射文件中通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型.假设现在有个比较复杂的查询需求:完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息.其它信息,比如商品.订单的),那么我们单纯的传入一个User就不行了,所以首先我们得根

mybatis 输入、输出映射

一.输入映射 mapper.xml的参数只有一个.可以传参数,基本简单类型,hashmap和javabean (一).Javabean的方法. 需求:通过小说名和作者模糊找书. 1.定义Javabean class  NovelCustom  extends Novel 继承了Novel.一个可以通过什么属性来查询.二.可以在里面加属性.如加上章节名来查询.(表tb_chacter和类Chacter,表中tb_novel_id外键), 或者,将Novel注入到NovelCustom.//priv

Mybatis映射原理,动态SQL,log4j

1.理清mybatis中的#和$之间的区别? #{ }:表示一个预处理参数,参数类型不定,是根据传入的参数类型来设定的. 类似于JDBC中的? 特例使用,模糊查询:(针对oracle): and username like concat(concat('%',#{username}),'%') 采取的$的方式传入参数,所有采取$的方式传入的参数都只是字符串(无论传入的是什么,都会当成字符串处理),潜在的危险就是SQL注入的问题. and username like '%${value}%' 注意

C++学习42 输入和输出的概念

我们经常用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上.从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件.除了以终端为对象进行输入和输出外,还经常用磁盘(光盘)作为输入输出对象,磁盘文件既可以作为输入文件,也可以作为输出文件. 程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件. C++输入输出包含以下三个方面的内容: 对系统指定的标准设备的输入和输出.即从键盘输入数据,输出到显示器屏幕.这种输入输出称为标

深入浅出Mybatis系列(九)---强大的动态SQL(转载)

原文出处:http://www.cnblogs.com/dongying/p/4092662.html 上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis强大的动态SQL. 那么,问题来了: 什么是动态SQL? 动态SQL有什么作用? 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Myba

深入浅出Mybatis系列(九)---强大的动态SQL

原文地址:http://www.cnblogs.com/dongying/p/4092662.html 上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis强大的动态SQL. 那么,问题来了: 什么是动态SQL? 动态SQL有什么作用? 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Myba

MyBatis学习15-MyBatis输入映射

1.通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型: 2.传递pojo的包装对象 完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息.其它信息,比如商品.订单的),针对这个需求,建议使用自定义的包装类型的pojo,在包装类型的pojo中将复杂的查询条件包装进去.po是持久层的对象,vo是视图层(表现层)的对象,pojo是自定义的类似于po或vo的综合体的简单Java bean. package po; //User的扩展类p

MyBatis学习(四)XML配置文件之SQL映射的XML文件

SQL映射文件常用的元素: 1.select 查询语句是MyBatis最常用的语句之一. 执行简单查询的select元素是非常简单的: <select id="selectUser" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = #{id} </select> 这个语句被称作selectUser,接受一个int类型的参数,

MyBatis学习(三)-XML映射文件(上)

XML映射文件即Mapper XML 有下列几个顶级元素: cache - 给定命名空间的缓存配置 cache-ref - 缓存配置的引用 resultMap - 描述结果集,是最强大也是最复杂的元素(没有之一) sql - 可复用的语句块 insert update delete select(从前往后说,本次是cache.cache-ref) MyBatis缓存机制 # 一级缓存(默认开启,SqlSession级别的缓存) 我们通过MyBatis每连接一次数据库就会创建一个SqlSessio

MyBatis学习总结(三)---映射文件及引入方式

MyBatis的强大,主要原于它强大映射功能,相对其它的jdbc,使用MyBatis,你会发现省掉很多代码.上一篇已经简单做出一个实例.今天就了解一下MyBatis的映射xml文件. 了解上一篇friendMapper.xml文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"