Mybatis输入输出映射及动态sql

来源:互联网 发布:百度软件开放平台 编辑:程序博客网 时间:2024/06/07 03:02

实体类User

public class User implements Serializable {    private Integer id;    private String username;    private String password;    private Date birthday;    private String address;    public User() {    }    public User(String username, String password, Date birthday, String address) {        this.username = username;        this.password = password;        this.birthday = birthday;        this.address = address;    }    get、set、toString方法}

mybatis配置文件中

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><typeAliases>    <package name="com.scu.mybatis.entity"/></typeAliases>    <environments default="development">        <environment id="development">            <!-- 使用jdbc事务管理 -->            <transactionManager type="JDBC" />            <!-- 数据库连接池 -->            <dataSource type="POOLED">                <property name="driver" value="com.mysql.jdbc.Driver" />                <property name="url"                    value="jdbc:mysql://localhost:3306/mybatis2?characterEncoding=utf-8" />                <property name="username" value="root" />                <property name="password" value="123456" />            </dataSource>        </environment>    </environments>    <mappers>        <mapper resource="com/scu/mybatis/entity/User.xml"/>    </mappers></configuration>

映射文件User.xml中

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.scu.mybatis.mapper.UserMapper">    <!-- 插入数据 -->    <insert id="save" parameterType="com.scu.mybatis.entity.User">    <selectKey keyProperty="id" order="AFTER" resultType="int">        SELECT LAST_INSERT_ID()    </selectKey>        INSERT INTO t_user (username,password,birthday,address) VALUES(#{username},#{password},#{birthday},#{address})    </insert>    <!-- 根据id查询数据 -->    <select id="findById" parameterType="int" resultType="com.scu.mybatis.entity.User">        SELECT * FROM t_user u WHERE u.id=#{id}     </select>    <!-- 查询所有用户信息 -->    <select id="findList" resultType="com.scu.mybatis.entity.User">        SELECT * FROM t_user    </select>    <!-- 根据用户名模糊查询,一定要写成value不能写成username -->    <select id="findByName" resultType="com.scu.mybatis.entity.User" parameterType="string">        SELECT * FROM t_user u WHERE u.username LIKE '%${value}%'     </select>    <!-- 修改用户信息 -->    <update id="updateById" parameterType="com.scu.mybatis.entity.User">        UPDATE t_user u SET u.username=#{username},u.password=#{password},            u.birthday=#{birthday},u.address=#{address}        WHERE u.id=#{id}     </update>    <!-- 删除 -->    <deleteid="delete" parameterType="int">        DELETE FROM t_user  WHERE id=#{id}     </delete></mapper>

mapper接口UserMapper

public interface UserMapper {    //插入数据    public void save(User user);    //根据id查询数据     public User findById(int id);    //查询所有用户信息    public List<User> findList();    //根据用户名模糊查询    public List<User> findByName(String username);    //修改用户信息    public void updateById(User user);    //删除用户    public void delete(int id);}

t_user表中几类如下
这里写图片描述

1、mybatis输入映射

在映射文件中parameterType表示输入类型
1.1、输入简单类型,如int,string类型
如上:根据id查询用户信息,根据用户名模糊查询
1.2、输入实体类型
如上:修改用户信息,传入的就是实体类User
1.3、输入包装类型(类A里面包装了类B)
比如类QueryVo中包装了实体类User
需求:使用包装类型,根据用户名模糊查询

public class QueryVo {    private User user;    getset方法}

User.xml中:使用实体类名.属性名

<!-- 包装类模糊查询 -->    <select id="findByQueryVo" parameterType="com.scu.mybatis.entity.QueryVo" resultType="com.scu.mybatis.entity.User">        SELECT * FROM t_user u WHERE u.username LIKE '%${user.username}%'    </select>

mapper接口中添加该方法

//根据包装类进行模糊查询public List<User> findByQueryVo(QueryVo vo);

测试:

@Test    /*     * 根据包装vo进行模糊查询     */    public void testQueryByVo(){        UserMapper mapper = session.getMapper(UserMapper.class);        QueryVo vo = new QueryVo();        User user = new User();        user.setUsername("小");        vo.setUser(user);        List<User> list = mapper.findByQueryVo(vo);        for (User user2 : list) {            System.out.println(user2);        }    }

输出:

User [id=2, username=小红, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=四川省成都市武侯区]User [id=3, username=小雨, password=123456, birthday=Sat Sep 02 00:00:00 CST 2017, address=安徽池州市]

2、输出类型
resultType可以表示输出类型
2.1、输出简单类型,比如查询用户表记录数
映射文件中

<!-- 查询用户表记录条数 -->    <select id="findCount" resultType="int">        SELECT COUNT(id) FROM t_user     </select>

UserMapper接口中

//查询用户表记录条数public int findCount();

2.2、输出实体类型
根据id查询用户信息,查询全部用户等都输出的是实体类型,如上。

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
但是,如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

创建订单表t_user,并且添加一条信息

CREATE TABLE `t_order` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `create_time` datetime NOT NULL,  `channel` int(2) NOT NULL,  `payment` int(32) NOT NULL,  `status` int(2) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8

创建对应实体类

public class Order {    private int id;    private Date createTime;    //支付方式 0:支付宝 1:微信    private int channel;    //支付金额    private int payment;    //支付状态 0:待支付 1:未支付 2:已支付    private int status;    public Order(Date createTime, int channel, int payment, int status) {        this.createTime = createTime;        this.channel = channel;        this.payment = payment;        this.status = status;    }    public Order() {    }    getset、toString方法}

注:创建时间在实体类中为createTime,在表中的字段为create_time

创建sql映射文件Order.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.scu.mybatis.mapper.OrderMapper">    <select id="findById" parameterType="int" resultType="order">        SELECT * FROM t_order WHERE id=#{id}    </select></mapper>

在sqlMapConfig中指定位置

<mappers>        <mapper resource="com/scu/mybatis/entity/User.xml"/>        <mapper resource="com/scu/mybatis/entity/Order.xml"/>    </mappers>

创建mapper接口OrderMapper

public interface OrderMapper {    public Order findById(int id);}

根据id订单信息

        @Test        /*         * 查询订单信息,字段属性不一致的为null         */        public void testFindById(){            OrderMapper mapper = session.getMapper(OrderMapper.class);            Order order = mapper.findById(1);            System.out.println(order);        }

输出:

Order [id=1, createTime=null, channel=1, payment=999, status=0]

能正确执行,不一致的字段createTime为显示null值(属性为引用类型),其他属性会正常显示。

使用resultMap来进行指定不一致字段,一致的字段可以指定也可以不指定。

<select id="findById" parameterType="int" resultMap="order1">        SELECT * FROM t_order WHERE id=#{id}    </select>    <resultMap type="Order" id="order1">        <result column="create_time" property="createTime"/>    </resultMap>

resultMap 标签中,id与resultMap输出一致,type则为指定输出类型。column指定表中字段,property指定与column不一致的属性。

再次测试输出,创建时间也能显示出来:

Order [id=1, createTime=Sat Sep 02 13:21:30 CST 2017, channel=1, payment=999, status=0]

3、动态sql
1、if,where标签
需求:根据住址(address)和用户名(username)查询用户信息
映射文件User.xml中

<!-- 根据用户名和地址查询用户 -->    <select id="findUserByAddrAndName" parameterType="user" resultType="user">        SELECT * FROM t_user          WHERE address=#{address} AND u.username LIKE '%${username}%'    </select>

mapper接口UserMapper中

    //根据用户名和地址查询用户    public List<User> findUserByAddrAndName(User user);

测试:

    @Test    public void testFindUserByAddrAndName(){        UserMapper mapper = session.getMapper(UserMapper.class);        User user = new User();        user.setUsername("小");        List<User> list = mapper.findUserByAddrAndName(user);        for (User user2 : list) {            System.out.println(user2);        }    }

因为住址设置的为null,所以是查不出任何数据的,这是不合理的,住址为null那么应该根据用户名去查,用户名为null那么也要根据住址去查的。
所以需要对两者进行非空判断

<select id="findUserByAddrAndName" parameterType="user" resultType="user">        SELECT * FROM t_user          WHERE         1=1        <if test="address != null and address != ''">        AND address=#{address}        </if>        <if test="username != null and username != ''">        AND username LIKE '%${username}%'        </if>    </select>

再次测试输出:

User [id=2, username=小红, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=四川省成都市武侯区]User [id=3, username=小雨, password=123456, birthday=Sat Sep 02 00:00:00 CST 2017, address=安徽池州市]

注:使用 “1=1”是为了防止address为空然后会多出来“and”
如果不使用”1=1”,那么可以使用where标签,如下

<select id="findUserByAddrAndName" parameterType="user" resultType="user">        SELECT * FROM t_user          <where>        <if test="address != null and address != ''">        AND address=#{address}        </if>        <if test="username != null and username != ''">        AND username LIKE '%${username}%'        </if>        </where>    </select>

where标签作用:1.顶替一个where关键字,2.去掉前面多余的and

2、sql,include标签
如果查询的时候不需要查询全部,只需要查询几个字段,封装到user对象中,而且很多地方都需要使用,那么可以使用sql标签指定需要的字段,然后使用include标签引入(比如表中有大文本信息,那么经常不需要查询大文本字段)。

比如根据id查询用户信息,但是只需要id,username,address三个字段。

    <sql id="userInfo">        id,username,address    </sql>    <select id="findById2" parameterType="int" resultType="User">        SELECT <include refid="userInfo"/> FROM t_user WHERE id=#{id}    </select>

mapper接口中

    //sql标签    public User findById2(int id);

测试

    @Test    /*     * sql标签测试,并不需要对应的构造方法就能进行封装     */    public void testFindById2(){        UserMapper mapper = session.getMapper(UserMapper.class);        User user = mapper.findById2(2);        System.out.println(user.getId()+","+user.getUsername()+","+user.getAddress());    }

输出

2,小红,四川省成都市武侯区

注:使用mybatis即使只查询部分字段也能进行实体类封装,而不需要对应字段的构造方法,而hibernate和jpa需要对应的构造方法。

3、foreach标签
需求:根据多个id查询用户信息
foreach标签,进行遍历
collection:遍历的集合,一般为array(数组),list(集合),属性(包装类的属性,为数组或者集合)
item:遍历的项目,可以随便写,但是和后面的#{}里面要一致
open:在前面添加的sql片段
close:在结尾处添加的sql片段
separator:指定遍历的元素之间使用的分隔符
3.1、使用数组

    <!-- foreach标签 -->    <select id="findListByIds1" resultType="User">        select * from t_user        where         id in        <foreach collection="array" item="item" separator="," open="(" close=")">            #{item}        </foreach>    </select>

mapper接口中

public List<User> findListByIds1(int[] ids);

测试:

@Test    public void testFindListByIds1(){        UserMapper mapper = session.getMapper(UserMapper.class);        int[] ids = {2,3};        List<User> list = mapper.findListByIds1(ids);        for (User user : list) {            System.out.println(user);        }    }

输出:

User [id=2, username=小红, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=四川省成都市武侯区]User [id=3, username=小雨, password=123456, birthday=Sat Sep 02 00:00:00 CST 2017, address=安徽池州市]

3.2、使用集合

<select id="findListByIds2" resultType="User">        select * from t_user        where         id in        <foreach collection="list" item="item" separator="," open="(" close=")">            #{item}        </foreach>    </select>
public List<User> findListByIds2(List<Integer> ids);

测试

@Test    public void testFindListByIds2(){        UserMapper mapper = session.getMapper(UserMapper.class);        List<Integer> list = new ArrayList<Integer>();        list.add(2);        list.add(3);        List<User> userList = mapper.findListByIds2(list);        for (User user : userList) {            System.out.println(user);        }    }

输出结果同上
3.2、使用包装类型QueryVo

public class QueryVo {    private User user;    private Integer[] ids;    getset方法}
<select id="findListByQueryVo" parameterType="QueryVo" resultType="User">        select * from t_user        where         id in        <foreach collection="ids" item="item" separator="," open="(" close=")">            #{item}        </foreach>    </select>

测试:

@Test    public void testFindListByQueryVo(){        UserMapper mapper = session.getMapper(UserMapper.class);        Integer[] ids = {2,3};        QueryVo vo = new QueryVo();        vo.setIds(ids);        List<User> userList = mapper.findListByQueryVo(vo);        for (User user : userList) {            System.out.println(user);        }    }

测试效果同上

原创粉丝点击