输入和输出映射,Mybatis学习笔记二【韦德娱乐

2019-05-12 08:01 来源:未知

1. 学习计划

1、输入映射和输出映射

a) 输入参数映射

b) 返回值映射

2、动态sql

a) If标签

b) Where标签

c) Sql片段

d) Foreach标签

3、关联查询

a) 一对一关联

b) 一对多关联

4、Mybatis整合spring

a) 如何整合spring

b) 使用原始的方式开发dao

c) 使用Mapper接口动态代理

5、Mybatis逆向工程(掌握)

一、输入映射和输出映射

本篇内容,紧接上一篇内容 Mybatis学习笔记一

2. 输入映射和输出映射

Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

1.1 parameterType(输入类型)

输入映射和输出映射

传递简单类型和pojo类型上篇已介绍过,下面介绍一下包装类型。

2.1. 环境准备

  1. 复制昨天的工程,按照下图进行

 韦德娱乐1946网页版 1

 

2.如下图粘贴,并更名

 韦德娱乐1946网页版 2

 

 3.只保留Mapper接口开发相关的文件,其他的删除

最终效果如下图:

 韦德娱乐1946网页版 3

 

 4.如下图修改SqlMapConfig.xml配置文件。Mapper映射器只保留包扫描的方式

 韦德娱乐1946网页版 4

 

【传递简单类型】

传递pojo包装对象

开发中通过可以使用pojo传递查询条件。查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。包装对象即Pojo类中的一个属性是另外一个pojo。

演示:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。

1、编写QueryVo

package com.yyb.pojo;

import java.io.Serializable;

/**
 * Created by Administrator on 2017/8/16.
 */
public class QueryVo implements Serializable{
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    private User user;

}

2、userMapper配置

    <select id="findByQueryVo"  parameterType="QueryVo" resultType="User">
        SELECT * FROM user WHERE username  like "%"#{user.username}"%"
    </select>

3.、userMapper接口中添加

 List<User> findByQueryVo(QueryVo vo);

4、测试类

    @org.junit.Test
    public void func2() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        QueryVo vo=new QueryVo();
        User u=new User();
        u.setUsername("五");
        vo.setUser(u);
        List<User> us = userMapper.findByQueryVo(vo);
        for (User use:us) {
            System.out.println(use);
        }
    }

2.2. parameterType(输入类型)

详情参考Mybatis学习笔记之一(环境搭建和入门案例介绍)

resultType(输出类型)

1、输出简单类型。示例:查询用户表数据条数

在userMapper.xml中添加如下代码:

   <select id="findUserCount"  resultType="Integer">
        SELECT COUNT(*) FROM user
    </select>

在userMapper接口中添加以下代码:

 int findUserCount();

测试方法

    @org.junit.Test
    public void func3() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int count = userMapper.findUserCount();
        System.out.println(count);
    }

注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

2、输出pojo对象,参考上篇

3、输出pojo列表,参考上篇

4、resultMap

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

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

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

示例:查询订单表order的所有数据

添加Order实体

韦德娱乐1946网页版 5韦德娱乐1946网页版 6

package com.yyb.pojo;

import java.io.Serializable;
import java.util.Date;

public class Orders  implements Serializable{
    private static final long serialVersionUID = 1L;

    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }



}

Orders .java

添加orderMapper.xml,在其中添加如下代码:

<?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="com.yyb.mapper.OrderMapper" >
    <resultMap id="orders" type="Orders" >
        <!--<id column="id" property="id"></id>-->
      <result column="user_id" property="userId" ></result>
    </resultMap>
    <select id="queryOrderList" resultMap="orders">
       SELECT id,user_id,number,createtime, note FROM orders
    </select>
</mapper>

添加orderMapper接口,在其中添加以下代码:

package com.yyb.mapper;

import com.yyb.pojo.Orders;

import java.util.List;

public interface OrderMapper {
    List<Orders> queryOrderList();
}

测试类

package com.yyb.test;

import com.yyb.mapper.OrderMapper;
import com.yyb.pojo.Orders;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;

/**
 * Created by Administrator on 2017/8/16.
 */
public class TestOrder {
    @org.junit.Test
    public void func1() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        OrderMapper userMapper = sqlSession.getMapper(OrderMapper.class);
        List<Orders> orders = userMapper.queryOrderList();
        for (Orders o:orders) {
            System.out.println(o);
        }
    }
}

由于sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来。

2.2.1. 传递简单类型

参考第一天内容。

使用#{}占位符,或者${}进行sql拼接。

 

使用#{}占位符,或者${}进行sql拼接。

动态sql

通过mybatis提供的各种标签方法实现动态拼接sql。

示例:根据性别和名字查询用户

在userMapper接口中添加如下代码:

 List<User> findUserByWhere(User user);

在userMapper.xml中添加如下代码:

 <select id="findUserByWhere" parameterType="User" resultType="User">
        SELECT id, username, birthday, sex, address FROM user
        WHERE 1=1
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE "%"#{username}"%"
        </if>
    </select>

测试方法如下:

@org.junit.Test
    public void func4() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User u=new User();
        u.setUsername("张");
        //u.setSex("1");
        List<User> us = userMapper.findUserByWhere(u);
        for (User use:us) {
            System.out.println(use);
        }
    }

2.2.2. 传递pojo对象

参考第一天的内容。

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

 

【传递pojo对象】

If标签

注意字符串类型的数据需要要做不等于空字符串校验。

        WHERE 1=1
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE "%"#{username}"%"
        </if>

2.2.3. 传递pojo包装对象

开发中通过可以使用pojo传递查询条件。

查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

包装对象:Pojo类中的一个属性是另外一个pojo。

 

需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。

 

详情参考Mybatis学习笔记之一(环境搭建和入门案例介绍)

Where标签

上面的sql还有where 1=1 这样的语句,很麻烦,可以使用where标签进行改造,where标签可以自动添加where,同时处理sql语句中第一个and关键字。

改造UserMapper.xml,如下:

 <select id="findUserByWhere" parameterType="User" resultType="User">
        SELECT id, username, birthday, sex, address FROM user
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE '%${username}%'
            </if>
        </where>
    </select>

2.2.3.1. 编写QueryVo

public class QueryVo {
    // 包含其他的pojo
    private User user;

    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

 

 

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:

<!--sql片段-->
<sql id="selector">
    SELECT id, username, birthday, sex, address FROM user
</sql>

 <select id="findUserByWhere" parameterType="User" resultType="User">
        <include refid="selector"/>
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE '%${username}%'
            </if>
        </where>
    </select>

如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace,例如下图

韦德娱乐1946网页版 7

2.2.3.2. Sql语句

SELECT * FROM user WHERE username LIKE '%张%'

1.2 传递pojo包装对象

foreach标签

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

示例:根据多个id查询用户信息

添加接口 findUserByIds

改造QueryVo

韦德娱乐1946网页版 8韦德娱乐1946网页版 9

package com.yyb.pojo;

import java.io.Serializable;
import java.util.List;

/**
 * Created by Administrator on 2017/8/16.
 */
public class QueryVo implements Serializable{
    private User user;

    List<Integer> idsList;

    Integer[] ids;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    public List<Integer> getIdsList() {
        return idsList;
    }
    public void setIdsList(List<Integer> idsList) {
        this.idsList = idsList;
    }
    public Integer[] getIds() {
        return ids;
    }
    public void setIds(Integer[] ids) {
        this.ids = ids;
    }
}

View Code

UserMapper.xml文件

 <select id="findUserByIds" parameterType="QueryVo" resultType="User">
        <include refid="selector"/>
        <where>
            <!-- foreach标签,进行遍历 -->
            <!-- collection:遍历的集合,这里是QueryVo的ids属性,当不使用包装类,直接传递数组或者list时,collection="Array" 或者collection="list" -->
            <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
            <!-- open:在前面添加的sql片段 -->
            <!-- close:在结尾处添加的sql片段 -->
            <!-- separator:指定遍历的元素之间使用的分隔符 -->
            <foreach collection="idsList" item="item" open="id IN (" close=")" separator=",">
                #{item}
            </foreach>
        </where>
    </select>

测试方法:

    @org.junit.Test
    public void func5() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
       QueryVo vo=new QueryVo();
       List<Integer>list=new ArrayList<>();
        list.add(16);
        list.add(24);
        list.add(30);
        vo.setIdsList(list);
        List<User> us = userMapper.findUserByIds(vo);
        for (User use:us) {
            System.out.println(use);
        }
    }

2.2.3.3. Mapper.xml文件

在UserMapper.xml中配置sql,如下图。

 韦德娱乐1946网页版 10

 

  开发中通过可以使用pojo传递查询条件。查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

关联查询

商品订单数据模型

 韦德娱乐1946网页版 11

方式一:定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段(继承现有pojo)。此方法较为简单,企业中使用普遍。

下面介绍方式二,使用resultMap,定义专门的resultMap用于映射一对一查询结果。

2.2.3.4. Mapper接口

在UserMapper接口中添加方法,如下图:

 韦德娱乐1946网页版 12

 

  包装对象:Pojo类中的一个属性是另外一个pojo。

一对一查询

示例:查询所有订单信息,关联查询下单用户信息。

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

在OrderMapper添加接口   List<Orders> queryOrderUser(); 

在Order类中添加如下代码:

  //在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。    
  private User user;

    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

在OrderMapper.xml中添加如下代码:

 <resultMap id="orderuser" type="Orders">
        <id column="id" property="id"></id>
        <result column="user_id" property="userId"></result>
        <result column="number" property="number"></result>
        <result column="createtime" property="createtime"></result>
        <result column="note" property="note"></result>

      <!-- association :配置一对一属性 -->

      <!-- property:order里面的User属性名 -->

      <!-- javaType:属性类型 -->

        <association property="user" javaType="User">
            <id column="user_id" property="id"></id>
            <result column="username" property="username"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
            <result column="address" property="address"></result>
        </association>
    </resultMap>
    <select id="queryOrderUser" resultMap="orderuser">
       SELECT
            o.id,o.user_id,o.number,o.createtime, o.note ,
            u.username,u.sex,u.birthday,u.address
        FROM orders  o
        LEFT JOIN USER u
        ON o.user_id=u.id
    </select>

测试代码:

 @org.junit.Test
    public void func2() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        OrderMapper userMapper = sqlSession.getMapper(OrderMapper.class);
        List<Orders> orders = userMapper.queryOrderUser();
        for (Orders o:orders) {//打断点调试查看user对象的值
            System.out.println(o);
        }
    }

2.2.3.5. 测试方法

在UserMapeprTest增加测试方法,如下:

@Test
public void testQueryUserByQueryVo() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行查询,使用包装对象
    QueryVo queryVo = new QueryVo();
    // 设置user条件
    User user = new User();
    user.setUsername("张");
    // 设置到包装对象中
    queryVo.setUser(user);

    // 执行查询
    List<User> list = userMapper.queryUserByQueryVo(queryVo);
    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

 

  需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。

 一对多查询

案例:查询所有用户信息及用户关联的订单信息。

用户信息和订单信息为一对多关系。

修改pojo类,在User类中加入List<Order>属性,如下:

    private List<Orders>lsOrders;

    public List<Orders> getLsOrders() {
        return lsOrders;
    }

    public void setLsOrders(List<Orders> lsOrders) {
        this.lsOrders = lsOrders;
    }

在userMapper接口中添加如下接口:  List<Orders> queryOrderUser(); 

在UserMapper.xml添加如下代码:

<resultMap id="userorder" type="User">
        <id column="user_id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
        <result column="address" property="address"></result>

        <collection property="lsOrders" ofType="Orders">
            <id column="id" property="id"></id>
            <result column="user_id" property="userId"></result>
            <result column="number" property="number"></result>
            <result column="createtime" property="createtime"></result>
            <result column="note" property="note"></result>
        </collection>
    </resultMap>
    <select id="findUserOrders" resultMap="userorder">
        SELECT
            u.username,u.sex,u.birthday,u.address,
            o.id,o.user_id,o.number,o.createtime, o.note
        FROM USER u
        LEFT JOIN orders  o
        ON o.user_id=u.id
    </select>

测试代码如下:

@org.junit.Test
    public void func6() throws Exception {
        //加载核心配置文件
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //SqlSEssion帮我生成一个实现类  (给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> us = userMapper.findUserOrders();
        for (User u:us) {
            System.out.println(u);
        }
    }

2.2.3.6. 效果

测试结果如下图:

 韦德娱乐1946网页版 13

 

 

 

 

【编写QueryVo类】

Mybatis整合spring

2.3. resultType(输出类型)

package com.kevin.entity;

import java.io.Serializable;
import java.util.List;

import com.kevin.entity.User;

public class QueryVo implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private User user;

    public void setUser(User user) {
        this.user = user;
    }
}

整合思路

  1. SqlSessionFactory对象应该放到spring容器中作为单例存在。
  2. 传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
  3. Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
  4. 数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

2.3.1. 输出简单类型

需求:查询用户表数据条数

 

sql:SELECT count(*) FROM `user`

 

Mapper.xml文件

整合需要的jar包

  1. spring的jar包
  2. Mybatis的jar包
  3. Spring mybatis的整合包。
  4. Mysql的数据库驱动jar包。
  5. 数据库连接池的jar包。

jar包如下所示:

韦德娱乐1946网页版 14

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yyb</groupId>
    <artifactId>ssm_crm</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>ssm_crm Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.1.3.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.7</version>
        </dependency>
        <!--mybatis-spring适配器 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--Spring框架核心库 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <!--spring-context,spring-core,spring-expression,spring-aop以及spring-beans-->
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <!--spring-orm,spring-jdbc和spring-tx-->
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <!--spring-web ,spring-webmvc-->
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.8</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.6</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>mybatis</finalName>
        <!--配置jdk版本为1.8-->
        <plugins>
            <!--解决自定义标签被覆盖-->
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <execution>
                        <!-- 在打包成功后使用tomcat:run来运行服务 -->
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

2.3.1.1. Mapper.xml文件

在UserMapper.xml中配置sql,如下图:

 韦德娱乐1946网页版 15

 

 

在UserMapper.xml中配置sql,如下:

加入配置文件

1、SqlMapConfig.xml,在resource目录下创建SqlMapConfig.xml,内容如下:

<?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>
        <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
        <package name="com.yyb.pojo" />
    </typeAliases>
</configuration>

2、applicationContext.xml,在resource目录下创建applicationContext.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:db.properties" />

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="5" />
    </bean>

    <!-- 配置mybatis的工厂 SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 配置mybatis核心配置文件 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml" />
        <!-- 配置数据源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

3、db.properties,在resource文件加下创建db.properties文件,内容如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybitis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

4、log4j.properties,在resource文件加下创建log4j.properties文件,内容如下:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

2.3.1.2. Mapper接口

在UserMapper添加方法,如下图:

 韦德娱乐1946网页版 16

 

 

    <!-- 根据QueryVo查询 -->
    <select id="findUserByQueryVo" parameterType="QueryVo" resultType="User">
        select * from User where username like "%"#{user.username}"%"
    </select>

Dao的开发

两种dao的实现方式:

1、原始dao的开发方式

原始的DAO开发接口 实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类。创建UserDao接口文件和UserDaoImpl.java文件。实现类的代码如下:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
}

在applicationContext中添加如下代码:

 <bean id="userDao" class="com.yyb.dao.UserDaoImpl" >
        <property name="sqlSessionFactory" ref="sqlSessionFactoryBean"></property>
    </bean>

2、使用Mapper代理形式开发方式

a)直接配置Mapper代理

    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="sqlSessionFactory" ref="sqlSessionFactoryBean"></property>
        <property name="mapperInterface" value="com.yyb.mapper.UserMapper"></property>
    </bean>

测试代码:

  @org.junit.Test
    public void func1() throws Exception {
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        //UserMapper mapper= (UserMapper) ac.getBean("userMapper");
        UserMapper mapper=ac.getBean(UserMapper.class);
        User user = mapper.findUserById(10);
        System.out.println(user);
    }

b)使用扫描包配置Mapper代理

  <!--mapper动态代理扫描-->
   <bean id="userMapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
       <property name="basePackage" value="com.yyb.mapper"></property>
   </bean>

2.3.1.3. 测试方法

在UserMapeprTest增加测试方法,如下:

@Test
public void testQueryUserCount() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行查询用户数据条数
    int count = userMapper.queryUserCount();
    System.out.println(count);

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

【Mapper接口】

Mybatis逆向工程

使用官方网站的Mapper自动生成工具mybatis-generator-core-1.3.2来生成pojo类和Mapper映射文件。

详情参考这里

注意:

1.逆向工程生成的代码只能做单表查询

2.不能在生成的代码上进行扩展,因为如果数据库变更,需要重新使用逆向工程生成代码,原来编写的代码就被覆盖了。

3.一张表会生成4个文件

 

mybatis中文文档地址

本文源码下载地址

SSM整合例子

2.3.1.4. 效果

测试结果如下图:

 韦德娱乐1946网页版 17

 

注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

 

在UserMapper接口中添加方法,如下:

2.3.2. 输出pojo对象

参考第一天内容

    /*
     * 使用QueryVo根据用户名称模糊查询
     */
    public List<User> findUserByQueryVo(QueryVo vo);

2.3.3. 输出pojo列表

参考第一天内容。

【测试方法】

2.4. resultMap

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

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

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

 

需求:查询订单表order的所有数据

sql:SELECT id, user_id, number, createtime, note FROM `order`

在UserMapeprTest增加测试方法,如下:

2.4.1. 声明pojo对象

数据库表如下图:

 韦德娱乐1946网页版 18

 

 

Order对象:

public class Order {
    // 订单id
    private int id;
    // 用户id
    private Integer userId;
    // 订单号
    private String number;
    // 订单创建时间
    private Date createtime;
    // 备注
    private String note;
get/set。。。
}

 

 

    /*
     * 使用QueryVo根据用户名称模糊查询
     */
    @Test
    public void findUserByQueryVo() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("王");
        vo.setUser(user);

        List<User> list = userMapper.findUserByQueryVo(vo);
        for (User user2 : list) {
            System.out.println(user2);
        }
    }

2.4.2. Mapper.xml文件

创建OrderMapper.xml配置文件,如下:

<?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">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,Mapper动态代理开发的时候使用,需要指定Mapper的类路径 -->
<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">
    <!-- 查询所有的订单数据 -->
    <select id="queryOrderAll" resultType="order">
        SELECT id, user_id,
        number,
        createtime, note FROM `order`
    </select>
</mapper>

 

1.3 resultType(输出类型)

2.4.3. Mapper接口

编写接口如下:

 

public interface OrderMapper {
    /**
     * 查询所有订单
     * 
     * @return
     */
    List<Order> queryOrderAll();
}public interface OrderMapper {
    /**
     * 查询所有订单
     * 
     * @return
     */
    List<Order> queryOrderAll();
}

 

1.3.1 输出简单类型

2.4.4. 测试方法

编写测试方法OrderMapperTest如下:

public class OrderMapperTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testQueryAll() {
        // 获取sqlSession
        SqlSession sqlSession = this.sqlSessionFactory.openSession();
        // 获取OrderMapper
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);

        // 执行查询
        List<Order> list = orderMapper.queryOrderAll();
        for (Order order : list) {
            System.out.println(order);
        }
    }
}

 

 

需求:查询用户表数据条数

2.4.5. 效果

测试效果如下图:

 韦德娱乐1946网页版 19

 

发现userId为null

解决方案:使用resultMap

 

Mapper.xml文件

2.4.6. 使用resultMap

由于上边的mapper.xml中sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。

需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来

 

改造OrderMapper.xml,如下:

<?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">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,Mapper动态代理开发的时候使用,需要指定Mapper的类路径 -->
<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">

    <!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
    <!-- id:设置ResultMap的id -->
    <resultMap type="order" id="orderResultMap">
        <!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
        <!-- property:主键在pojo中的属性名 -->
        <!-- column:主键在数据库中的列名 -->
        <id property="id" column="id" />

        <!-- 定义普通属性 -->
        <result property="userId" column="user_id" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </resultMap>

    <!-- 查询所有的订单数据 -->
    <select id="queryOrderAll" resultMap="orderResultMap">
        SELECT id, user_id,
        number,
        createtime, note FROM `order`
    </select>

</mapper>

 

 

在UserMapper.xml中配置sql,如下:

2.4.7. 效果

只需要修改Mapper.xml就可以了,再次测试结果如下:

 韦德娱乐1946网页版 20

 

 

    <!-- 查询数据条数 -->
    <select id="countUser" resultType="Integer">
        select count(*) from User
    </select>

3. 动态sql

通过mybatis提供的各种标签方法实现动态拼接sql。

 

需求:根据性别和名字查询用户

查询sql:

SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%张%'

Mapper接口

3.1. If标签

在UserMapper添加方法,如下:

3.1.1. Mapper.xml文件

UserMapper.xml配置sql,如下:

 

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
    WHERE sex = #{sex} AND username LIKE
    '%${username}%'
</select>

 

/*
     * 查询数据条数
     */
    public Integer countUser();

3.1.2. Mapper接口

编写Mapper接口,如下图:

 韦德娱乐1946网页版 21

 

 

【 测试方法】

3.1.3. 测试方法

在UserMapperTest添加测试方法,如下:

 

@Test
public void testQueryUserByWhere() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    User user = new User();
    user.setSex("1");
    user.setUsername("张");

    List<User> list = userMapper.queryUserByWhere(user);

    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

/*
     * 查询数据条数
     */
    @Test
    public void countUser() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        Integer count = userMapper.countUser();
        System.out.println(count);

    }

3.1.4. 效果

测试效果如下图:

 韦德娱乐1946网页版 22

 

 

如果注释掉 user.setSex("1"),测试结果如下图:

 韦德娱乐1946网页版 23

 

测试结果二很显然不合理。

按照之前所学的,要解决这个问题,需要编写多个sql,查询条件越多,需要编写的sql就更多了,显然这样是不靠谱的。

 

解决方案,使用动态sql的if标签

 

style="font-family: "Microsoft YaHei"; font-size: 15px">Tips:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

3.1.5. 使用if标签

改造UserMapper.xml,如下:

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
    WHERE 1=1
    <if test="sex != null and sex != ''">
        AND sex = #{sex}
    </if>
    <if test="username != null and username != ''">
        AND username LIKE
        '%${username}%'
    </if>
</select>

 

 

注意字符串类型的数据需要要做不等于空字符串校验。

1.3.2 输出pojo对象

3.1.6. 效果

 韦德娱乐1946网页版 24

 

如上图所示,测试OK

 

详情参考Mybatis学习笔记之一(环境搭建和入门案例介绍)

3.2. Where标签

上面的sql还有where 1=1 这样的语句,很麻烦

可以使用where标签进行改造

 

改造UserMapper.xml,如下

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
    <where>
        <if test="sex != null">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </where>
</select>

 

 

1.3.3 输出pojo列表

3.2.1. 效果

测试效果如下图:

 韦德娱乐1946网页版 25

 

 

详情参考Mybatis学习笔记之一(环境搭建和入门案例介绍)

3.3. Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

 

把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    <!-- SELECT id, username, birthday, sex, address FROM `user` -->
    <!-- 使用include标签加载sql片段;refid是sql片段id -->
    SELECT <include refid="userFields" /> FROM `user`
    <!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
    <where>
        <if test="sex != null">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </where>
</select>

<!-- 声明sql片段 -->
<sql id="userFields">
    id, username, birthday, sex, address
</sql>

 

 

如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace

例如下图

 韦德娱乐1946网页版 26

 

1.4 resultMap

3.4. foreach标签

向sql传递数组或List,mybatis使用foreach解析,如下:

 

根据多个id查询用户信息

查询sql:

SELECT * FROM user WHERE id IN (1,10,24)

 

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

3.4.1. 改造QueryVo

如下图在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法

 韦德娱乐1946网页版 27

 

 

需求:查询订单表order的所有数据

3.4.2. Mapper.xml文件

UserMapper.xml添加sql,如下:

<!-- 根据ids查询用户 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
    SELECT * FROM `user`
    <where>
        <!-- foreach标签,进行遍历 -->
        <!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
        <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
        <!-- open:在前面添加的sql片段 -->
        <!-- close:在结尾处添加的sql片段 -->
        <!-- separator:指定遍历的元素之间使用的分隔符 -->
        <foreach collection="ids" item="item" open="id IN (" close=")"
            separator=",">
            #{item}
        </foreach>
    </where>
</select>

 

 

测试方法如下图:

@Test
public void testQueryUserByIds() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    QueryVo queryVo = new QueryVo();
    List<Integer> ids = new ArrayList<>();
    ids.add(1);
    ids.add(10);
    ids.add(24);
    queryVo.setIds(ids);

    List<User> list = userMapper.queryUserByIds(queryVo);

    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

【声明pojo对象】

3.4.3. 效果

测试效果如下图:

 韦德娱乐1946网页版 28

 

其他实现:

 韦德娱乐1946网页版 29

底层原理:传递进去的user并没有被引用,而是重新创建一个map把user里面的值存在map里面,传入如果是数组那就会放在array中,如果是List就会放在list中。

 韦德娱乐1946网页版 30

 

 

package com.kevin.entity;

import java.io.Serializable;
import java.util.Date;

public class Orders  implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

    @Override
    public String toString() {
        return "Orders [id="   id   ", userId="   userId   ", number="   number   ", createtime="   createtime
                  ", note="   note   "]";
    }



}

4. 关联查询

Mapper.xml文件

4.1. 商品订单数据模型

 韦德娱乐1946网页版 31

 

 

<?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="com.kevin.mapper.OrdersMapper">
    <!-- 查询所有数据 -->
    <select id="findAll" resultType="Orders">    
        select * from Orders
    </select>

</mapper>

4.2. 一对一查询

需求:查询所有订单信息,关联查询下单用户信息。

 

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

 

sql语句:

SELECT
    o.id,
    o.user_id userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
FROM
    `orders` o
LEFT JOIN `user` u ON o.user_id = u.id

 

 

Mapper接口

4.2.1. 方法一:使用resultType

使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息

这样返回对象的时候,mybatis自动把用户信息也注入进来了

package com.kevin.mapper;

import java.util.List;

import com.kevin.entity.Orders;

public interface OrdersMapper {

    /*
     * 查询所有数据(类属性与数据库字段不一致)
     */
    public List<Orders> findAll();

}

4.2.1.1. 改造pojo类

OrderUser类继承Order类后OrderUser类包括了Order类的所有字段,只需要定义用户的信息字段即可,如下图:

 韦德娱乐1946网页版 32

 

测试方法

4.2.1.2. Mapper.xml

在UserMapper.xml添加sql,如下

<!-- 查询订单,同时包含用户数据 -->
<select id="queryOrderUser" resultType="orderUser">
    SELECT
    o.id,
    o.user_id
    userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>

 

    /*
     *查询所有数据(属性名称与数据库字段名称不一致) 
     */
    @Test
    public void findAll() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = factory.openSession();
        OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);

        List<Orders> list = mapper.findAll();
        for (Orders order : list) {
            System.out.println(order);
        }

    }

4.2.1.3. 韦德娱乐1946网页版 ,Mapper接口

在UserMapper接口添加方法,如下图:

 韦德娱乐1946网页版 33

 

1.4.1 使用resultMap

4.2.1.4. 测试方法:

在UserMapperTest添加测试方法,如下:

@Test
public void testQueryOrderUser() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    List<OrderUser> list = userMapper.queryOrderUser();

    for (OrderUser ou : list) {
        System.out.println(ou);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

  由于上边的mapper.xml中sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来

4.2.1.5. 效果

测试结果如下图:

 韦德娱乐1946网页版 34

 

改造OrderMapper.xml,如下:

4.2.1.6. 小结

定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

 

<?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="com.kevin.mapper.OrdersMapper">
    <resultMap type="Orders" id="orders">
        <result column="user_id" property="userId"/>
    </resultMap>
    <!-- 查询所有数据 -->
    <!-- <select id="findAll" resultType="Orders"> -->
    <select id="findAll" resultMap="orders">
        select * from Orders
    </select>

</mapper>

4.2.2. 方法二:使用resultMap

使用resultMap,定义专门的resultMap用于映射一对一查询结果。

 

 

4.2.2.1. 改造pojo类

在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。

改造Order如下图:

 韦德娱乐1946网页版 35

 

 

二、动态sql拼接

4.2.2.2. Mapper.xml

这里resultMap指定orderUserResultMap,如下:

<resultMap type="order" id="orderUserResultMap">
    <id property="id" column="id" />
    <result property="userId" column="user_id" />
    <result property="number" column="number" />
    <result property="createtime" column="createtime" />
    <result property="note" column="note" />

    <!-- association :配置一对一属性 -->
    <!-- property:order里面的User属性名 -->
    <!-- javaType:属性类型 -->
    <association property="user" javaType="user">
        <!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
        <id property="id" column="user_id" />
        <result property="username" column="username" />
        <result property="address" column="address" />
    </association>

</resultMap>

<!-- 一对一关联,查询订单,订单内部包含用户属性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    SELECT
    o.id,
    o.user_id,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>

 

  通过mybatis提供的各种标签方法实现动态拼接sql。

4.2.2.3. Mapper接口

编写UserMapper如下图:

 韦德娱乐1946网页版 36

 

 

  需求:根据性别和名字查询用户

4.2.2.4. 测试方法

在UserMapperTest增加测试方法,如下:

@Test
public void testQueryOrderUserResultMap() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    List<Order> list = userMapper.queryOrderUserResultMap();

    for (Order o : list) {
        System.out.println(o);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

2.1 使用If标签和WHERE标签

4.2.2.5. 效果

测试效果如下图:

 韦德娱乐1946网页版 37

 

 

Mapper.xml文件

4.3. 一对多查询

案例:查询所有用户信息及用户关联的订单信息。

用户信息和订单信息为一对多关系。

 

sql语句:

SELECT
    u.id,
    u.username,
    u.birthday,
    u.sex,
    u.address,
    o.id oid,
    o.number,
    o.createtime,
    o.note
FROM
    `user` u
LEFT JOIN `order` o ON u.id = o.user_id

 

<!-- 多条件查询 where标签可以去掉前面第一个and -->
    <select id="findUserBySexAndUsername" parameterType="User" resultType="User">
       select * from User 
        <where>
            <if test="sex != null and sex != ''">
                sex = #{sex}
            </if>
            <if test="username != null">
                and username = #{username}
            </if>
        </where>
    </select>

4.3.1. 修改pojo类

在User类中加入List<Order> orders属性,如下图:

 韦德娱乐1946网页版 38

 

 

【Mapper接口】

4.3.2. Mapper.xml

在UserMapper.xml添加sql,如下:

<resultMap type="user" id="userOrderResultMap">
    <id property="id" column="id" />
    <result property="username" column="username" />
    <result property="birthday" column="birthday" />
    <result property="sex" column="sex" />
    <result property="address" column="address" />

    <!-- 配置一对多的关系 -->
    <collection property="orders" javaType="list" ofType="order">
        <!-- 配置主键,是关联Order的唯一标识 -->
        <id property="id" column="oid" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </collection>
</resultMap>

<!-- 一对多关联,查询订单同时查询该用户下的订单 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
    SELECT
    u.id,
    u.username,
    u.birthday,
    u.sex,
    u.address,
    o.id oid,
    o.number,
    o.createtime,
    o.note
    FROM
    `user` u
    LEFT JOIN `order` o ON u.id = o.user_id
</select>

 

编写Mapper接口,如下:

4.3.3. Mapper接口

编写UserMapper接口,如下图:

 韦德娱乐1946网页版 39

 

 

    /*
     * 多条件查询
     */
    public List<User> findUserBySexAndUsername(User user);

4.3.4. 测试方法

在UserMapperTest增加测试方法,如下

@Test
public void testQueryUserOrder() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    List<User> list = userMapper.queryUserOrder();

    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 

测试方法

4.3.5. 效果

测试效果如下图:

 韦德娱乐1946网页版 40

 

 

 

 

在UserMapperTest添加测试方法,如下:

5. Mybatis整合spring

/*
     * 多条件查询
     */
    @Test
    public void findUserBySexAndUsername() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = factory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = new User();
        user.setUsername("Kevin");
        user.setSex("Male");

        List<User> list = mapper.findUserBySexAndUsername(user);
        for (User u: list) {
            System.out.println(u);
        }

    }

5.1. 整合思路

1、SqlSessionFactory对象应该放到spring容器中作为单例存在。

2、传统dao的开发方式中,应该从spring容器中获得sqlsession对象。

3、Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。

4、数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

2.2 Sql片段

5.2. 整合需要的jar包

1、spring的jar包

2、Mybatis的jar包

3、Spring mybatis的整合包。

4、Mysql的数据库驱动jar包。

5、数据库连接池的jar包。

jar包位置如下所示:

 韦德娱乐1946网页版 41

  Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

5.3. 整合的步骤

  把上面例子中的select * from User 提取出来,作为sql片段,如下:

5.3.1. 创建工程

如下图创建一个java工程:

 韦德娱乐1946网页版 42

 

  <!-- 提取SQL语句中重复片段 -->
  <sql id="selector">
    select * from User 
  </sql>

   <!-- 多条件查询 where标签可以去掉前面第一个and -->
    <select id="findUserBySexAndUsername" parameterType="User" resultType="User">
        <include refid="selector"></include>
        <where>
            <if test="sex != null and sex != ''">
                sex = #{sex}
            </if>
            <if test="username != null">
                and username = #{username}
            </if>
        </where>
    </select>

5.3.2. 导入jar包

前面提到的jar包需要导入,如下图:

 韦德娱乐1946网页版 43

 

 

2.3 foreach标签

5.3.3. 加入配置文件

  1. mybatisSpring的配置文件
  2. 的配置文件sqlmapConfig.xml

a) 数据库连接及连接池

b) 事务管理(暂时可以不配置)

c) sqlsessionFactory对象,配置到spring容器中

d) mapeer代理对象或者是dao实现类配置到spring容器中。

 

创建资源文件夹config拷贝加入配置文件,如下图

 韦德娱乐1946网页版 44

 

 

需求:根据多个id查询用户信息

5.3.3.1. SqlMapConfig.xml

配置文件是SqlMapConfig.xml,如下:

<?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>
        <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
        <package name="cn.itcast.mybatis.pojo" />
    </typeAliases>

</configuration>

 

 

改造QueryVo

5.3.3.2. applicationContext.xml

SqlSessionFactoryBean属于mybatis-spring这个jar包

对于spring来说,mybatis是另外一个架构,需要整合jar包。

 

在项目中加入mybatis-spring-1.2.2.jar的源码,如下图

 韦德娱乐1946网页版 45

韦德娱乐1946网页版 46

 

 

 

效果,如下图所示,图标变化,表示源码加载成功:

 韦德娱乐1946网页版 47

 

整合Mybatis需要的是SqlSessionFactoryBean,位置如下图:

 韦德娱乐1946网页版 48

 

 

applicationContext.xml,配置内容如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

   <!-- 加载配置文件 -->
   <context:property-placeholder location="classpath:db.properties" />

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="5" />
    </bean>

    <!-- 配置SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 配置mybatis核心配置文件 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml" />
        <!-- 配置数据源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

 

如下面在pojo中定义list属性ids存储多个用户id,并添加setter方法

5.3.3.3. db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
package com.kevin.entity;

import java.io.Serializable;
import java.util.List;

import com.kevin.entity.User;

public class QueryVo implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private User user;

    private List<Integer> list;

    public void setList(List<Integer> list) {
        this.list = list;
    }


    public void setUser(User user) {
        this.user = user;
    }


}

5.3.3.4. log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

Mapper.xml文件

5.3.3.5. 效果:

加入的配置文件最终效果如下:

 韦德娱乐1946网页版 49

 

UserMapper.xml添加sql,如下:

5.4. Dao的开发

两种dao的实现方式:

1、原始dao的开发方式

2、使用Mapper代理形式开发方式

a) 直接配置Mapper代理

b) 使用扫描包配置Mapper代理

 

需求:

  1. 实现根据用户id查询
  2. 实现根据用户名模糊查询
  3. 添加用户

 

    <!--  根据多个id查询 -->
    <select id="findUserByIds" parameterType="QueryVo" resultType="User">
        <include refid="selector"></include>
        where id in
        <foreach collection="list" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </select> 

5.4.1. 创建pojo

public class User {
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

get/set。。。
}

 

 

【测试方法】

5.4.2. 传统dao的开发方式

原始的DAO开发接口 实现类来完成。

需要dao实现类需要继承SqlsessionDaoSupport类

 

    /*
     *根据多个id查询
     */
    @Test
    public void findUserByIds() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = factory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        
        /*
         * 使用QueryVo中的List列表
         */
        List<Integer> lists = new ArrayList<Integer>();
        lists.add(28);
        lists.add(29);
        lists.add(25);
        lists.add(30);
        QueryVo vo = new QueryVo();
        vo.setList(lists);

        List<User> list = mapper.findUserByIds(lists);
        for (User u: list) {
            System.out.println(u);
        }
    }

5.4.2.1. 实现Mapper.xml

编写User.xml配置文件,如下:

<?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="test">
    <!-- 根据用户id查询 -->
    <select id="queryUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    </select>

    <!-- 根据用户名模糊查询用户 -->
    <select id="queryUserByUsername" parameterType="string"
        resultType="user">
        select * from user where username like '%${value}%'
    </select>

    <!-- 添加用户 -->
    <insert id="saveUser" parameterType="user">
        <selectKey keyProperty="id" keyColumn="id" order="AFTER"
            resultType="int">
            select last_insert_id()
        </selectKey>
        insert into user
        (username,birthday,sex,address)
        values
        (#{username},#{birthday},#{sex},#{address})
    </insert>

</mapper>

 

 

5.4.2.2. 加载Mapper.xml

在SqlMapConfig如下图进行配置:

 韦德娱乐1946网页版 50

 

 

三、关联查询

5.4.2.3. 实现UserDao接口

public interface UserDao {
    /**
     * 根据id查询用户
     * 
     * @param id
     * @return
     */
    User queryUserById(int id);

    /**
     * 根据用户名模糊查询用户列表
     * 
     * @param username
     * @return
     */
    List<User> queryUserByUsername(String username);

    /**
     * 保存
     * 
     * @param user
     */
    void saveUser(User user);

}

 

 

 

3.1  一对一查询

5.4.2.4. 实现UserDaoImpl实现类

编写DAO实现类,实现类必须集成SqlSessionDaoSupport

SqlSessionDaoSupport提供getSqlSession()方法来获取SqlSession

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
    @Override
    public User queryUserById(int id) {
        // 获取SqlSession
        SqlSession sqlSession = super.getSqlSession();

        // 使用SqlSession执行操作
        User user = sqlSession.selectOne("queryUserById", id);

        // 不要关闭sqlSession

        return user;
    }

    @Override
    public List<User> queryUserByUsername(String username) {
        // 获取SqlSession
        SqlSession sqlSession = super.getSqlSession();

        // 使用SqlSession执行操作
        List<User> list = sqlSession.selectList("queryUserByUsername", username);

        // 不要关闭sqlSession

        return list;
    }

    @Override
    public void saveUser(User user) {
        // 获取SqlSession
        SqlSession sqlSession = super.getSqlSession();

        // 使用SqlSession执行操作
        sqlSession.insert("saveUser", user);

        // 不用提交,事务由spring进行管理
        // 不要关闭sqlSession
    }
}

 

 

需求:查询所有订单信息,关联查询下单用户信息。

5.4.2.5. 配置dao

把dao实现类配置到spring容器中,如下图

 韦德娱乐1946网页版 51

 

 

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

5.4.2.6. 测试方法

创建测试方法,可以直接创建测试Junit用例。

如下图所示进行创建。

 韦德娱乐1946网页版 52

韦德娱乐1946网页版 53

韦德娱乐1946网页版 54

 

编写测试方法如下:

 

public class UserDaoTest {
    private ApplicationContext context;

    @Before
    public void setUp() throws Exception {
        this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }

    @Test
    public void testQueryUserById() {
        // 获取userDao
        UserDao userDao = this.context.getBean(UserDao.class);

        User user = userDao.queryUserById(1);
        System.out.println(user);
    }

    @Test
    public void testQueryUserByUsername() {
        // 获取userDao
        UserDao userDao = this.context.getBean(UserDao.class);

        List<User> list = userDao.queryUserByUsername("张");
        for (User user : list) {
            System.out.println(user);
        }
    }

    @Test
    public void testSaveUser() {
        // 获取userDao
        UserDao userDao = this.context.getBean(UserDao.class);

        User user = new User();
        user.setUsername("曹操");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("三国");
        userDao.saveUser(user);
        System.out.println(user);
    }
}

 

方法一:使用resultType

5.4.3. Mapper代理形式开发dao

  使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息,这样返回对象的时候,mybatis自动把用户信息也注入进来了。

5.4.3.1. 实现Mapper.xml

编写UserMapper.xml配置文件,如下:

<?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="cn.itcast.mybatis.mapper.UserMapper">
    <!-- 根据用户id查询 -->
    <select id="queryUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    </select>

    <!-- 根据用户名模糊查询用户 -->
    <select id="queryUserByUsername" parameterType="string"
        resultType="user">
        select * from user where username like '%${value}%'
    </select>

    <!-- 添加用户 -->
    <insert id="saveUser" parameterType="user">
        <selectKey keyProperty="id" keyColumn="id" order="AFTER"
            resultType="int">
            select last_insert_id()
        </selectKey>
        insert into user
        (username,birthday,sex,address) values
        (#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>

 

改造pojo类

5.4.3.2. 实现UserMapper接口

public interface UserMapper {
    /**
     * 根据用户id查询
     * 
     * @param id
     * @return
     */
    User queryUserById(int id);

    /**
     * 根据用户名模糊查询用户
     * 
     * @param username
     * @return
     */
    List<User> queryUserByUsername(String username);

    /**
     * 添加用户
     * 
     * @param user
     */
    void saveUser(User user);
}

 

  OrderUser类继承Order类后OrderUser类包括了Order类的所有字段,只需要定义用户的信息字段即可,如下图:

5.4.3.3. 方式一:配置mapper代理

在applicationContext.xml添加配置

MapperFactoryBean也是属于mybatis-spring整合包

<!-- Mapper代理的方式开发方式一,配置Mapper代理对象 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <!-- 配置Mapper接口 -->
    <property name="mapperInterface" value="cn.itcast.mybatis.mapper.UserMapper" />
    <!-- 配置sqlSessionFactory -->
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

 

 韦德娱乐1946网页版 55

5.4.3.4. 测试方法

public class UserMapperTest {
    private ApplicationContext context;

    @Before
    public void setUp() throws Exception {
        this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }

    @Test
    public void testQueryUserById() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

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

    @Test
    public void testQueryUserByUsername() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

        List<User> list = userMapper.queryUserByUsername("张");

        for (User user : list) {
            System.out.println(user);
        }
    }
    @Test
    public void testSaveUser() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

        User user = new User();
        user.setUsername("曹操");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("三国");

        userMapper.saveUser(user);
        System.out.println(user);
    }
}

 

 

Mapper.xml

5.4.3.5. 方式二:扫描包形式配置mapper

<!-- Mapper代理的方式开发方式二,扫描包方式配置代理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 配置Mapper接口 -->
    <property name="basePackage" value="cn.itcast.mybatis.mapper" />
</bean>

 

每个mapper代理对象的id就是类名,首字母小写

在UserMapper.xml添加sql,如下

6. Mybatis逆向工程

使用官方网站的Mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和Mapper映射文件

<!-- 查询订单,同时包含用户数据 -->

<select id="queryOrderUser" resultType="orderUser">
SELECT
o.id,
o.user_id
userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
</select>

6.1. 导入逆向工程

使用课前资料已有逆向工程,如下图:

 韦德娱乐1946网页版 56

 

 

Mapper接口

6.1.1. 复制逆向工程到工作空间中

复制的效果如下图:

 韦德娱乐1946网页版 57

 

 

在UserMapper接口添加方法,如下图:

6.1.2. 导入逆向工程到eclipse中

如下图方式进行导入:

 韦德娱乐1946网页版 58

韦德娱乐1946网页版 59

韦德娱乐1946网页版 60

 

 

 韦德娱乐1946网页版 61

6.2. 修改配置文件

在generatorConfig.xml中配置Mapper生成的详细信息,如下图:

 韦德娱乐1946网页版 62

 

注意修改以下几点:

  1. 修改要生成的数据库表
  2. pojo文件所在包路径
  3. Mapper所在的包路径

 

配置文件如下:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="testTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root">
        </jdbcConnection>
        <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 
            userId="yycg" password="yycg"> </jdbcConnection> -->

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 
            和 NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="cn.itcast.ssm.po"
            targetProject=".src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="cn.itcast.ssm.mapper"
            targetProject=".src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- targetPackage:mapper接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="cn.itcast.ssm.mapper" targetProject=".src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 指定数据库表 -->
        <table schema="" tableName="user"></table>
        <table schema="" tableName="order"></table>
    </context>
</generatorConfiguration>

 

测试方法

6.3. 生成逆向工程代码

找到下图所示的java文件,执行工程main主函数,

 韦德娱乐1946网页版 63

韦德娱乐1946网页版 64

 

 

 

刷新工程,发现代码生成,如下图:

 韦德娱乐1946网页版 65

 

在UserMapperTest添加测试方法,如下:

6.4. 测试逆向工程代码

  1. 复制生成的代码到mybatis-spring工程,如下图

 韦德娱乐1946网页版 66

 

 

  1. 修改spring配置文件

在applicationContext.xml修改

 

<!-- Mapper代理的方式开发,扫描包方式配置代理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 配置Mapper接口,如果需要加载多个包,直接写进来,中间用,分隔 -->
    <!-- <property name="basePackage" value="cn.itcast.mybatis.mapper" /> -->
    <property name="basePackage" value="cn.itcast.ssm.mapper" />
</bean>

 

 

  1. 编写测试方法:

 

public class UserMapperTest {
    private ApplicationContext context;

    @Before
    public void setUp() throws Exception {
        this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }

    @Test
    public void testInsert() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

        User user = new User();
        user.setUsername("曹操");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("三国");

        userMapper.insert(user);
    }

    @Test
    public void testSelectByExample() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

        // 创建User对象扩展类,用户设置查询条件
        UserExample example = new UserExample();
        example.createCriteria().andUsernameLike("%张%");

        // 查询数据
        List<User> list = userMapper.selectByExample(example);

        System.out.println(list.size());
    }

    @Test
    public void testSelectByPrimaryKey() {
        // 获取Mapper
        UserMapper userMapper = this.context.getBean(UserMapper.class);

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

 

注意:

  1. 逆向工程生成的代码只能做单表查询
  2. 不能在生成的代码上进行扩展,因为如果数据库变更,需要重新使用逆向工程生成代码,原来编写的代码就被覆盖了。
  3. 一张表会生成4个文件

 

@Test

public void testQueryOrderUser() {
// mybatis和spring整合,整合之后,交给spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 创建Mapper接口的动态代理对象,整合之后,交给spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
List<OrderUser> list = userMapper.queryOrderUser();
for (OrderUser ou : list) {
System.out.println(ou);
}
// mybatis和spring整合,整合之后,交给spring管理

sqlSession.close();
}

 

小结

  定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

方法二:使用resultMap

  使用resultMap,定义专门的resultMap用于映射一对一查询结果。

改造pojo类

  在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。

  改造Order如下:

package com.kevin.entity;

import java.io.Serializable;
import java.util.Date;

public class Orders  implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note; 
    private User user;
    public void setUser(User user) {
        this.user = user;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

    @Override
    public String toString() {
        return "Orders [id="   id   ", userId="   userId   ", number="   number   ", createtime="   createtime
                  ", note="   note   "]";
    }



}

Mapper.xml

    <!-- 一对一关联查询 -->
    <resultMap type="Orders" id="order">
        <result column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <!-- 一对一 -->
        <association property="user" javaType="User">
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
        </association>
    </resultMap>
    <select id="selectOrders" resultMap="order">
        select
        o.id,
        o.user_id,
        o.number,
        o.createtime,
        u.username
        from orders o
        left join user u
        on o.user_id = u.id
    </select>

Mapper接口

    /*
     * 一对一关联查询,以订单为中心关联用户
     */
    public List<Orders> selectOrders();

测试方法

在UserMapperTest增加测试方法,如下:

    /*
     * 一对一查询
     */
    @Test
    public void selectOrders() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);

        List<Orders> selectOrders = mapper.selectOrders();
        for (Orders orders : selectOrders) {
            System.out.println(orders);
        }        
    }

3.2  一对多查询

  案例:查询所有用户信息及用户关联的订单信息。用户信息和订单信息为一对多关系。

修改pojo类

在User类中加入List<Orders> ordersList属性,如下:

package com.kevin.entity;

import java.util.Date;
import java.util.List;

public class User {
    /**
     * 创建一个简单的bean
     */
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    private List<Orders> ordersList;



    public List<Orders> getOrdersList() {
        return ordersList;
    }
    public void setOrdersList(List<Orders> ordersList) {
        this.ordersList = ordersList;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User [id="   id   ", username="   username   ", sex="   sex
                  ", birthday="   birthday   ", address="   address   "]";
    }


}

Mapper.xml

<!-- /*
     * 一对多关联
     */
    public List<User> selectUsersList(); -->
    <resultMap type="User" id="user">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <!-- 一对多 -->
        <collection property="ordersList" ofType="Orders">
            <id column="id" property="id"/>
            <result column="number" property="number"/>
        </collection>
    </resultMap>
    <select id="selectUserList" resultMap="user">
        select
        o.id,
        o.user_id,
        o.number,
        o.createtime,
        u.username
        from user u
        left join orders o
        on o.user_id = u.id
    </select>

Mapper接口

编写UserMapper接口,如下:

   /*
     * 一对多关联
     */

    public List<User> selectUserList();

测试方法

/*
     * 一对多关联
     */
    @Test
    public void selectUsersList() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);

        List<User> selectUsersList = mapper.selectUserList();
        for (User user : selectUsersList) {
            System.out.println(user);
        }
    }

 

四、Mybatis整合spring

4.1 整合思路

  ● SqlSessionFactory对象应该放到spring容器中作为单例存在。

  ● 传统dao的开发方式中,应该从spring容器中获得sqlsession对象。

  ● Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。

  ● 数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

4.2 整合需要的jar包

  ● spring的jar包

  ● Mybatis的jar包

  ● Spring mybatis的整合包。

  ● Mysql的数据库驱动jar包。

  ● 数据库连接池的jar包。

4.3 整合的步骤

创建工程

创建一个java工程

导入jar包

前面提到的jar包需要导入,如下图:

韦德娱乐1946网页版 67

加入配置文件

  ● SqlMapConfig.xml.xml配置文件

  ● applicationContext.xml配置文件:

    a) 数据库连接及连接池

    b) 事务管理(暂时可以不配置)

    c) sqlsessionFactory对象,配置到spring容器中

    d) mapeer代理对象或者是dao实现类配置到spring容器中。

SqlMapConfig.xml

配置文件是SqlMapConfig.xml,如下:

<?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>
        <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
        <package name="com.kevin.entity" />
    </typeAliases>

    <mappers>
        <package name="com.kevin.mapper"/>
    </mappers>

</configuration>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="5" />
    </bean>

    <!-- mybatis工厂 -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 配置数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 配置mybatis核心配置文件 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
    </bean>


</beans>    

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=admin

log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

4.4  Dao的开发

两种dao的实现方式:

  ● 原始dao的开发方式

  ● 使用Mapper代理形式开发方式

    a) 直接配置Mapper代理

    b) 使用扫描包配置Mapper代理

需求:

  1. 实现根据用户id查询

  2. 实现根据用户名模糊查询

  3. 添加用户

  传统方式Dao开发可参考Mybatis学习笔记之一(环境搭建和入门案例介绍),下面主要介绍Mapper动态代理形式开发。

4.5 Mapper代理形式开发

实现Mapper.xml

编写UserMapper.xml配置文件,如下:

<?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="com.kevin.mapper.UserMapper">

    <select id="findUserById" parameterType="Integer" resultType="User">
        select * from User where id = #{id}
    </select>

</mapper>

实现UserMapper接口

package com.kevin.mapper;

import java.util.List;

import com.kevin.entity.User;

public interface UserMapper {

    public User findUserById(Integer id);

} 

方式一:配置mapper代理

在applicationContext.xml添加配置

<!-- mapper动态代理开发 -->
    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="sqlSessionFactory" ref="sqlSessionFactoryBean"></property>
        <property name="mapperInterface" value="com.kevin.mapper.UserMapper"></property>
    </bean>

测试方法

    /*
     * mapper动态代理开发
     */
    @Test
    public void findUserById(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//        context.getBean(UserMapper.class);
        UserMapper userMapper = (UserMapper) context.getBean("userMapper");
        User user = userMapper.findUserById(1);
        System.out.println(user);

    }

方式二:扫描包形式配置mapper

在applicationContext.xml添加配置

    <!-- mapper动态代理开发,扫描 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 基本包 -->
        <property name="basePackage" value="com.kevin.mapper"></property>
    </bean>

测试方法

/*
     * 增强mapper动态代理开发
     */
    @Test
    public void findUserById2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper mapper = context.getBean(UserMapper.class);
        User user = mapper.findUserById(30);
        System.out.println(user);

    }

 

TAG标签: 韦德娱乐1946
版权声明:本文由韦德娱乐1946_韦德娱乐1946网页版|韦德国际1946官网发布于韦德娱乐1946网页版,转载请注明出处:输入和输出映射,Mybatis学习笔记二【韦德娱乐