20160522--20160526----mybatis入门基础

一、基础知识:

 1.对原生态jdbc程序(单独使用jdbc开发)问题总结

 2.mybatis框架原理 (掌握)

 3.mybatis入门程序

 4.用户的增、删、改、查

 5.SqlMapConfig.xml

 6.输入映射

 7.输出映射

 8.动态sql

 

1.对原生态jdbc程序中问题总结

1.1 环境

java环境:jdk1.8.0_20

eclipse:luna

mysql5.1

1.2   创建mysql数据

sql脚本:

/*
SQLyog v10.2 
MySQL - 5.1.72-community : Database - mybatis
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*Table structure for table `items` */

CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL COMMENT '商品名称',
  `price` float(10,1) NOT NULL COMMENT '商品定价',
  `detail` text COMMENT '商品描述',
  `pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
  `createtime` datetime NOT NULL COMMENT '生产日期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*Table structure for table `orderdetail` */

CREATE TABLE `orderdetail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orders_id` int(11) NOT NULL COMMENT '订单id',
  `items_id` int(11) NOT NULL COMMENT '商品id',
  `items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`orders_id`),
  KEY `FK_orderdetail_2` (`items_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Table structure for table `orders` */

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '下单用户id',
  `number` varchar(32) NOT NULL COMMENT '订单号',
  `createtime` datetime NOT NULL COMMENT '创建订单时间',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Table structure for table `user` */

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
sql脚本

1.3 jdbc程序

使用jdbc查询mysql数据库中用户表的记录。

创建java工程,加入jar包:

数据库驱动包(mysql5.1

 

上边的是mysql驱动。

下边的是oracle的驱动。

 程序代码:

package com.dzq.mybatis.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 通过Jdbc程序,总结单独的jdbc程序,总结其中
 * 
 * @author 小强
 *
 */
public class JdbcTest {
    public static void main(String[] args) {
        // 数据库连接
        Connection connection = null;
        // 预编译的Statement,可以提高数据库的性能
        PreparedStatement preparedStatement = null;
        // 结果集对象
        ResultSet resultSet = null;

        try {
            // 加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");

            // 通过驱动管理类获取数据库链接
            connection = DriverManager
                    .getConnection(
                            "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
                            "root", "mysql");
            // 定义sql语句 ?表示占位符
            String sql = "select * from user where username = ?";
            // 获取预处理statement
            preparedStatement = connection.prepareStatement(sql);
            // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            // 向数据库发出sql执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            // 遍历查询结果集
            while (resultSet.next()) {
                System.out.println(resultSet.getString("id") + "  "
                        + resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }

}
JdbcTest

1.4  问题总结

1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响 数据库性能。

设想:使用数据库连接池管理数据库连接。

2、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。

设想:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。

3、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。

设想:将sql语句及占位符号和参数全部配置在xml中。

4、从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。

设想:将查询的结果集,自动映射成java对象。

2.mybatis框架

2.1     mybatis是什么?

mybatis是一个持久层的框架,是apache下的顶级项目。

mybatis托管到goolecode下,再后来托管到github下(https://github.com/mybatis/mybatis-3/releases)。

mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。

mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射

2.2    mybatis框架

3入门程序

3.1 需求

根据用户id(主键)查询用户信息

根据用户名称模糊查询用户信息

添加用户

删除 用户

更新用户

 

3.2 环境

java环境:jdk1.8.0_20

eclipse:luna

mysql:5.1

jar包:mybatis-3.2.7.jar

lib下:依赖包

mybatis-3.2.7.jar:核心 包

mybatis-3.2.7.pdf,操作指南

加入mysql的驱动包

3.3 log4j.properties

 

# Global logging configuration
#\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u65e5\u5fd7\u7ea7\u522b\u8981\u8bbe\u7f6e\u6210DEBUG\uff0c\u751f\u4ea7\u73af\u5883\u8bbe\u7f6e\u6210info\u6216error
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

3.4工程结构

 

3.5 SqlMapConfig.xml

配置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>

    
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
        <!-- 使用jdbc事务管理,事务控制由mybatis-->
            <transactionManager type="JDBC" />
        <!-- 数据库连接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>

</configuration>
SqlMapConfig.xml

 

3.6根据用户id(主键)查询用户信息

 

3.6.1 创建po

 

package com.dzq.mybatis.domain;

import java.util.Date;

public class User {
    // 属性名和数据库表的字段对应
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    public int getId() {
        return id;
    }

    public void setId(int 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;
    }

}
User.java

 

3.6.2    映射文件

映射文件命名:

User.xml(原始ibatis命名),mapper代理开发映射文件名称叫XXXMapper.xml,比如:UserMapper.xml、ItemsMapper.xml

在映射文件中配置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">
<!--命名空间,对sql进行分类管理,实现sql隔离 注意:使用mapper代理的方法开发,namespace就有特殊重要的作用 -->
<mapper namespace="test">
    <!-- 在映射文件中配置很多sql语句 -->
    <!-- 通过id查询用户表的记录 -->
    <!--通过select执行数据库的查询 
    id:标识映射文件中的sql,称为statemen的id 将sql语句封装到mappedstatement对象中
    #{}:表示占位符
    parameterType:指定输入参数类型,这里指定int型
    {id}:其中的id表示接收输入参数,如果输入参数是简单类型,#{}中参数名可以任意,可以是value或者其他名称
    resultType:指定sql输出结果所映射的java对象类型,select指定resultType将单条记录所映射成的java对象
     -->
    <select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">
     select * from user where id=#{id}
    </select>
</mapper>
User.xml

 

3.6.3     在SqlMapConfig.xml加载映射文件

在sqlMapConfig.xml中加载User.xml:

<!-- 加载 映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
    </mappers>

3.6.4     程序编写

package com.dzq.mybatis.first;

import java.io.IOException;
import java.io.InputStream;

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 com.dzq.mybatis.domain.User;

public class MybatisFirst {
    // 根据id查询用户的信息,得到一条记录结果
    public void findUserById(int id) throws IOException {
        //mybatis配置文件
        String resource="SqlMapConfig.xml";
        //得到配置文件流
        InputStream inputStream=Resources.getResourceAsStream(resource);
        //创建会话工厂,传入mybatis的配置文件的信息
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂得到sqlsession
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //通过sqlsession操作数据库
        //第一个参数:statement,映射文件中statement的id; 等于namespace+"."statement的id
        //第二个参数: parameter 指定和映射文件中parameter所匹配的parameterType的类型的 参数
        //sqlSession.selectOne结果是与映射文件中所匹配的resultType类型对象
        User user=sqlSession.selectOne("test.findUserById", 1);
        System.out.println(user);
        //释放资源
        sqlSession.close();
    }
}
MybatisFirst.java

 

3.7  根据用户名称模糊查询用户信息

3.7.1     映射文件

使用User.xml,添加根据用户名称模糊查询用户信息的sql语句。

<!-- 根据用户名称模糊查询用户信息  -->
    <!-- resultType:单条记录所映射的java对象类型
    ${}:拼接sql串,将接收到的参数不加任何修饰拼接到sql语句中
    使用${}拼接sql,会引起sql注入
    ${value}表示输入参数的内容,如果传入的类型是简单类型${}只能使用value
     -->
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.dzq.mybatis.domain.User">
         select * from user where username like '%${value}%'
    </select>

3.7.2   程序代码

//根据用户名称模糊查询用户信息
    public void findUserByUserName() throws IOException{
        //mybatis配置文件
                String resource="SqlMapConfig.xml";
                //得到配置文件流
                InputStream inputStream=Resources.getResourceAsStream(resource);
                //创建会话工厂,传入mybatis的配置文件的信息
                SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
                //通过工厂得到sqlsession
                SqlSession sqlSession=sqlSessionFactory.openSession();
                //通过sqlsession操作数据库
                //第一个参数:statement,映射文件中statement的id; 等于namespace+"."statement的id
                //第二个参数: parameter 指定和映射文件中parameter所匹配的parameterType的类型的 参数
                //sqlSession.selectList结果是与映射文件中所匹配的resultType类型对象
                List<User> list=sqlSession.selectList("test.findUserByUserName", "小明");
                System.out.println(list);
                //释放资源
                sqlSession.close();
    }

3.8添加用户

3.8.1映射文件

在 User.xml中配置添加用户的Statement

<!-- 添加用户 -->
    <!--  
    parameterType:输入参数类型是pojo(包括用户信息)
    #{}:指定pojo的属性名,接收到pojo的属性值,mybatis通过ognl获取属性值
    -->
    <insert id="addUser" parameterType="com.dzq.mybatis.domain.User">
        insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
    </insert>

 

3.8.2程序代码

//添加用户信息
    @Test
    public void addUser() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂,传入mybatis的配置文件的信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);
        // 通过工厂得到sqlsession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //插入用户对象
        User user=new User();
        user.setUsername("贱贱");
        user.setSex("男");
        user.setAddress("山东临沂");
        user.setBirthday(new Date());
       sqlSession.insert("test.addUser", user);
       //提交事务
       sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }

3.8.3    自增主键返回

mysql自增主键,执行insert提交之前自动生成一个自增主键。

通过mysql函数获取到刚插入记录的自增主键:

LAST_INSERT_ID()

是insert之后调用此函数。

修改insertUser定义:

<insert id="addUser" parameterType="com.dzq.mybatis.domain.User">
        <!-- insert 插入数据返回到User对象中 
         select last_insert_id:得到刚插入进去数据的主键值,只适用于自增主键
         keyProperty:将要查询到的主键值设置到parameterType对象的那个属性
         order:相对于insert语句的执行顺序
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id()
        </selectKey>
        insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
    </insert>

3.8.14    非自增主键返回(使用uuid())

使用mysql的uuid()函数生成主键,需要修改表中id字段类型为string,长度设置成35位。

执行思路:

先通过uuid()查询到主键,将主键输入 到sql语句中。

执行uuid()语句顺序相对于insert语句之前执行。

 

通过oracle的序列生成主键:

<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.Integer" order="BEFORE" 
keyProperty="id">
SELECT 自定义序列.NEXTVAL FROM DUAL
</selectKey>
insert into user(id,username,birthday,sex,address) 
         values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

注意这里使用的order是“BEFORE”

3.9删除用户

3.9.1映射文件

<!-- 删除用户
    根据id删除用户,需要输入id值
     -->
    <delete id="deleteUser" parameterType="int" >
        delete from user where id=#{id}
    </delete>

3.9.2程序代码

//删除用户信息
        @Test
        public void deleteUser() throws IOException {
            // mybatis配置文件
            String resource = "SqlMapConfig.xml";
            // 得到配置文件流
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 创建会话工厂,传入mybatis的配置文件的信息
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(inputStream);
            // 通过工厂得到sqlsession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //传入id,根据id删除用户
           sqlSession.delete("test.deleteUser", 33);
           //提交事务
           sqlSession.commit();
            // 释放资源
            sqlSession.close();
        }

 

3.10更新用户

3.10.1映射文件

<!-- 更新用户 
    分析:需要传入用户的id
    用户的更新信息
    parameterType,指定user对象,包括id和更新信息,注意,id必须存在
    #{id}接收user里的属性值
    -->
    <update id="updateUser" parameterType="com.dzq.mybatis.domain.User">
        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
    </update>

3.10.2程序代码

// 更新用户信息
    @Test
    public void updateUser() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂,传入mybatis的配置文件的信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);
        // 通过工厂得到sqlsession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        user.setId(32);
        user.setUsername("贱贱贱");
        user.setSex("女");
        user.setAddress("山东莱芜");
        user.setBirthday(new Date());
        // 传入user对象,根据id更新用户
        sqlSession.update("test.updateUser", user);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }

 

3.11小结

 3.11.1      #{}和${}

#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。

如果接收简单类型,#{}中可以写成value或其它名称。

#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。

${}接收输入参数,类型可以是简单类型,pojo、hashmap。

如果接收简单类型,${}中只能写成value。

${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

3.11.2     parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。

resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

3.11.3     selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

3.12   mybatis和hibernate本质区别和应用场景

hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。

对sql语句进行优化、修改比较困难的。

应用场景:

         适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。

mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。

应用场景:

         适用与需求变化较多的项目,比如:互联网项目。

企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。

4     mybatis开发dao的方法

4.1     SqlSession使用范围

4.1.1     SqlSessionFactoryBuilder

 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory

将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。

在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。

4.1.2   SqlSessionFactory

通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。

将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。

 

4.1.3    SqlSession

SqlSession是一个面向用户(程序员)的接口。

SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。

SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。

SqlSession最佳应用场合在方法体内,定义成局部变量使用。

4.2    原始dao开发方法(程序员需要写dao接口和dao实现类)

4.2.1     思路

程序员需要写dao接口和dao实现类。

需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

4.2.2     dao接口

package com.dzq.mybatis.dao;

import com.dzq.mybatis.domain.User;

public interface UserDao {
    // 根据id查询用户信息
    public User findUserById(int id) throws Exception;

    // 添加用户
    public void addUser(User user) throws Exception;

    // 删除用户
    public void deleteUser(int id) throws Exception;

    // 修改用户信息
    public void updateUser(User user) throws Exception;
}

 

4.2.2     dao接口实现类

package com.dzq.mybatis.dao.impl;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.dzq.mybatis.dao.UserDao;
import com.dzq.mybatis.domain.User;

public class UserDaoImpl implements UserDao {
    // 需要向dao实现类中注入SqlSessionFactory
    // 这里通过构造方法注入
    private SqlSessionFactory sqlSessionFactory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findUserById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", id);
        // 释放资源
        sqlSession.close();
        return user;
    }

    @Override
    public void addUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行插入
        sqlSession.insert("test.addUser", user);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }

    @Override
    public void deleteUser(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteUser", id);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();

    }

    @Override
    public void updateUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.update("test.updateUser", user);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }

}

4.2.4  测试代码:

package com.dzq.mybatis.test;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.dzq.mybatis.dao.UserDao;
import com.dzq.mybatis.dao.impl.UserDaoImpl;
import com.dzq.mybatis.domain.User;

public class UserDaoImplTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void setUp() throws Exception {
        // 创建sqlSessionFactory
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂,传入mybatis的配置文件的信息
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testFindUserById() throws Exception {
        // 创建UserDao对象
        UserDao userdao = new UserDaoImpl(sqlSessionFactory);
        // 调用userDao方法
        User user=userdao.findUserById(1);
        System.out.println(user.getUsername());
    }

}

 

4.2.5     总结原始 dao开发问题

1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。

 

2、调用sqlsession方法时将statement的id硬编码了

 

3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。

 

4.3    mapper代理方法(程序员只需要mapper接口(相当 于dao接口))

 

4.3.1     思路(mapper代理开发规范)

程序员还需要编写mapper.xml映射文件

程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。

 

开发规范:

1、在mapper.xml中namespace等于mapper接口地址

<!--命名空间,对sql进行分类管理,实现sql隔离 注意:使用mapper代理的方法开发,namespace就有特殊重要的作用 
namespace等于mapper接口地址
-->
<mapper namespace="com.dzq.mybatis.mapper.UserMapper">

 

2、mapper.java接口中的方法名和mapper.xml中statement的id一致

3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。

4、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。

<select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">
     select * from user where id=#{id}
    </select>
// 根据id查询用户信息
    public User findUserById(int id) throws Exception;

总结:

以上开发规范主要是对下边的代码进行统一生成:

User user = sqlSession.selectOne("test.findUserById", id);

sqlSession.insert("test.insertUser", user);

。。。。

4.3.2     mapper.java

package com.dzq.mybatis.mapper;

import java.util.List;

import com.dzq.mybatis.domain.User;

public interface UserMapper {
    
    public User findUserById(int id) throws Exception;
}

4.3.3 mapper.xml

<select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">
     select * from user where id=#{id}
    </select>
    

4.3.4     在SqlMapConfig.xml中加载mapper.xml

<!-- 加载 映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>

4.3.5    测试

package com.dzq.mybatis.test;

import java.io.InputStream;

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 org.junit.Before;
import org.junit.Test;

import com.dzq.mybatis.domain.User;
import com.dzq.mybatis.mapper.UserMapper;

public class UserMapperTest {
    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void setUp() throws Exception {
        // 创建sqlSessionFactory
                // mybatis配置文件
                String resource = "SqlMapConfig.xml";
                // 得到配置文件流
                InputStream inputStream = Resources.getResourceAsStream(resource);
                // 创建会话工厂,传入mybatis的配置文件的信息
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testFindUserById() throws Exception {
        
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //创建一个usermapper的对象
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        User user=userMapper.findUserById(1);
        System.out.println(user.getUsername());
        
    }

}

4.3.6    整个接口

package com.dzq.mybatis.mapper;

import java.util.List;

import com.dzq.mybatis.domain.User;

public interface UserMapper {

    // 根据id查询用户信息
    public User findUserById(int id) throws Exception;

    // 添加用户
    public void addUser(User user) throws Exception;

    // 删除用户
    public void deleteUser(int id) throws Exception;

    // 根据用户名称查询用户列表
    public List<User> findUserByUserName(String username) throws Exception;
}

4.3.7     一些问题总结

4.3.7.1              代理对象内部调用selectOne或selectList

如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。

如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。

4.3.7.2              mapper接口方法参数只能有一个是否影响系统 开发

mapper接口方法参数只能有一个,系统是否不利于扩展维护。

系统 框架中,dao层的代码是被业务层公用的。

即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。

 

注意:持久层方法的参数可以包装类型、map。。。,service方法中建议不要使用包装类型(不利于业务层的可扩展)。

 

5     SqlMapConfig.xml

mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:

 

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

 

5.1     properties属性

需求:

将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。

在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。

 

将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=
<!-- 加载属性文件 -->
    <properties resource="db.properties">
        <!--properties中还可以配置一些属性名和属性值 -->
        <!-- <property name="jdbc.driver" value=""/> -->
    </properties>

properties特性:

 

注意: MyBatis 将按照下面的顺序来加载属性:

      在 properties 元素体内定义的属性首先被读取。

      然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

      最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

 

建议:

不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。

在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

5.2   settings全局参数配置

 

mybatis框架在运行时可以调整一些运行参数。

比如:开启二级缓存、开启延迟加载。。

 

全局参数将会影响mybatis的运行行为。

 

5.3     typeAliases(别名)重点

 

5.3.1     需求

在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。

 

如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。

5.3.2   mybatis默认支持别名

5.3.3     自定义别名

 

5.3.3.1              单个别名定义

<!-- 别名定义 -->
    <typeAliases>
        <!-- 针对单个别名的定义
        type:类型路径
        alias:别名
         -->
        <typeAlias type="com.dzq.mybatis.domain.User" alias="user"/>
    </typeAliases>

 

引用别名:

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

5.3.3.2  批量定义别名(常用)

<!-- 批量别名定义
        指定包名,mybatis自动扫描domain类,自动定义别名,别名就是类名
         -->
         <package name="com.dzq.mybatis.domain"/>

5.4    typeHandlers(类型处理器)

mybatis中通过typeHandlers完成jdbc类型和java类型的转换。

 

通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.

 

mybatis支持类型处理器:

5.5  mappers(映射配置)

5.5.1     通过resource加载单个映射文件

<!-- 加载 映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml" />
        <mapper resource="mapper/UserMapper.xml" />
    </mappers>

5.5.2   通过mapper接口加载单个mapper

<!--通过mapper接口加载单个mapper 
        遵循一些规范:需要将mapper接口的类名和mapper.xml映射文件名称保持一致,且在一个目录
        上边规范的前提是:你使用的是mapper代理的方法
        -->
        <mapper class="com.dzq.mybatis.mapper.UserMapper"/>

需要将mapper接口的类名和mapper.xml映射文件名称保持一致,且在一个目录

5.5.3  批量加载mapper(推荐使用)

<!--批量加载mapper(推荐使用) 
        指定mapper接口的包名,mybatis自动扫描包下所有mapper接口进行加载
        遵循一些规范:需要将mapper接口的类名和mapper.xml映射文件名称保持一致,且在一个目录
        上边规范的前提是:你使用的是mapper代理的方法
         -->
        <package name="com.dzq.mybatis.mapper"/>

6    输入映射

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

6.1     传递pojo的包装对象

6.1.1     需求

完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其它信息,比如商品、订单的)

6.1.2     定义包装类型pojo

针对上边需求,建议使用自定义的包装类型的pojo。

在包装类型的pojo中将复杂的查询条件包装进去。

package com.dzq.mybatis.domain;

public class UserQueryVo {
//这里包装所需要的查询条件
    //用户查询条件
    private UserCustom userCustom;
    //还可以包装其他的查询条件 商品、订单

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }
    
}

6.1.3    mapper.xml

在UserMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂关联查询)。

 <!-- 用户信息的综合查询
    #{userCustom.sex}:取出包装类型的性别信息
    ${userCustom.username}:取出包装类中的用户名
     -->
    <select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">
        select * from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'
    </select>

6.1.4     mapper.java

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

 

6.1.5    测试代码

 @Test
    public void testFindUserList() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建一个usermapper的对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建包装对象,设置查询条件
        UserQueryVo userQueryVo=new UserQueryVo();
        UserCustom userCustom=new UserCustom();
        userCustom.setSex("1");
        userCustom.setUsername("小明");
        userQueryVo.setUserCustom(userCustom);
        // 调用userMapper方法
        
        List<UserCustom> list = userMapper.findUserList(userQueryVo);
        //sqlSession.close();
        System.out.println(list);

    }

 

7     输出映射

 

7.1     resultType

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

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

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

 

7.1.1     输出简单类型

7.1.1.1              需求

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

 

7.1.1.2              mapper.xml

<!-- 用户信息综合查询总数
    parameterType:输入类型和findUserList一致
    resultType:输出结果类型为整型
     -->
    <select id="findUserCount"  parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">
          select count(*) from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'
    </select>

 

7.1.1.3              mapper.java

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

 

7.1.1.4             测试代码

 @Test
    public void testFindUserCount() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建一个usermapper的对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建包装对象,设置查询条件
        UserQueryVo userQueryVo=new UserQueryVo();
        UserCustom userCustom=new UserCustom();
        userCustom.setSex("1");
        userCustom.setUsername("小明");
        userQueryVo.setUserCustom(userCustom);
        // 调用userMapper方法
        
        int count = userMapper.findUserCount(userQueryVo);
        System.out.println(count);

    }

7.1.1.5             小结

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

7.1.2   输出pojo对象和pojo列表

 

不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。

在mapper.java指定的方法返回值类型不一样:

         1、输出单个pojo对象,方法返回值是单个对象类型

          

    // 根据id查询用户信息
    public User findUserById(int id) throws Exception;

 

         2、输出pojo对象list,方法返回值是List<Pojo>

         

    // 根据用户名称查询用户列表
    public List<User> findUserByUserName(String username) throws Exception;

 

生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).

7.2     resultMap

mybatis中使用resultMap完成高级输出结果映射。(一对一、一对多、多对多)(小入门)

7.2.1     resultMap使用方法

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

1、定义resultMap

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

7.2.2     将下边的sql使用User完成映射

SELECT id id_,username username_ FROM USER WHERE id=#{value}

User类中属性名和上边查询列名不一致。

7.2.2.1              定义reusltMap

 <!-- 定义resultMap
    将 select id id_,username username_ from user where id=#{id}查询和User做一个映射
    type:resultMap最终映射的java对象类型,可以使用别名
    id:对resultMap的唯一标识
     -->
    <resultMap type="user" id="userResultMap">
        <!-- id表示查询结果集中唯一的标识 
        column:查询出来的列名
        property:type中指定的pojo中的属性名
        最终resultMap对column和property做一个映射关系(对应关系)
        -->
        <id column="id_" property="id"/>
        <!-- 对普通列的定义
        column:查询出来的列名
        property:type中指定的pojo中的属性名
        最终resultMap对column和property做一个映射关系(对应关系)
         -->
        <result column="username_" property="username"/>
        
    </resultMap>

 

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

 <!-- 使用resultMap来进行输出的映射 
    resultMap:指定定义的resultMap的id,如果resultMap在其他映射文件中,前边需要加上namespace
    
    -->
    <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
     select id id_,username username_ from user where id=#{id}
    </select>

7.2.2.3            mapper.java

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

7.2.2.4            测试

@Test
    public void testFindUserByIdResultMap() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建一个usermapper的对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 调用userMapper方法
        User user = userMapper.findUserByIdResultMap(1);
        System.out.println(user.getUsername());

    }

7.3    小结

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

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

8      动态sql

8.1     什么是动态sql

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

8.2     需求

用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql。

对查询条件进行判断,如果输入参数不为空才进行查询条件拼接。

8.3     mapper.xml

 <!-- 用户信息的综合查询
    #{userCustom.sex}:取出包装类型的性别信息
    ${userCustom.username}:取出包装类中的用户名
     -->
    <select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">
        select * from user 
        <!-- where 可以自动的去掉条件中的第一个and -->
        <where>
            <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
              and user.sex=#{userCustom.sex} 
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
              and user.username like '%${userCustom.username}%'
            </if>
        </if>
        </where>
        
        
    </select>
    
    <!-- 用户信息综合查询总数
    parameterType:输入类型和findUserList一致
    resultType:输出结果类型为整型
     -->
    <select id="findUserCount"  parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">
          select count(*) from user 
           <!-- where 可以自动的去掉条件中的第一个and -->
        <where>
            <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
              and user.sex=#{userCustom.sex} 
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
              and user.username like '%${userCustom.username}%'
            </if>
        </if>
        </where>
    </select>

8.4   测试代码

 public void testFindUserList() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建一个usermapper的对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建包装对象,设置查询条件
        UserQueryVo userQueryVo=new UserQueryVo();
        UserCustom userCustom=new UserCustom();
        
        //由于使用了动态sql,如果不设置某个值,这个条件不会拼接到sql中
        //userCustom.setSex("1");
        userCustom.setUsername("小明");
        userQueryVo.setUserCustom(userCustom);
        // 调用userMapper方法
        
        List<UserCustom> list = userMapper.findUserList(userQueryVo);
        //sqlSession.close();
        System.out.println(list);

    }

8.5    sql片段

 

8.5.1     需求

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

方便程序员进行开发。

 

8.5.2     定义sql片段

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

 

8.5.3    引用sql片段

在mapper.xml中定义的statement中引用sql片段:

 <!-- 用户信息的综合查询
    #{userCustom.sex}:取出包装类型的性别信息
    ${userCustom.username}:取出包装类中的用户名
     -->
    <select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">
        select * from user 
        <!-- where 可以自动的去掉条件中的第一个and -->
        <where>
            <!--  这就是引用sql片段的id 如果refid不在本mapper中,需要加上namespace-->
          <include refid="query_user_where"> </include>
          <!-- 在这里还会引用其他sql片段,商品等 -->
        </where>
        
        
    </select>
  <!-- 用户信息综合查询总数
    parameterType:输入类型和findUserList一致
    resultType:输出结果类型为整型
     -->
    <select id="findUserCount"  parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">
          select count(*) from user 
           <!-- where 可以自动的去掉条件中的第一个and -->
        <where>
              <!--  这就是引用sql片段的id 如果refid不在本mapper中,需要加上namespace-->
          <include refid="query_user_where"> </include>
          <!-- 在这里还会引用其他sql片段,商品等 -->
        </where>
    </select>

 

8.6    foreach

 

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

 

8.6.1     需求

 

在用户查询列表和查询总数的statement中增加多个id输入查询。

sql语句如下:

两种方法:

SELECT * FROM USER WHERE id=1 OR id=10 OR id=16

SELECT * FROM USER WHERE id IN(1,10,16)

8.6.2    在输入参数类型中添加List<Integer> ids传入多个id

 

    //传入多个id
        private List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

 

8.6.3     修改mapper.xml

WHERE id=1 OR id=10 OR id=16

在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。

 <if test="ids!=null">
                <!-- 使用foreach遍历我们传入的ids 
                collection:指定输入对象中集合属性
                item:每次遍历生成对象名
                open:开始遍历时要拼接的串
                close:结束遍历时拼接的串
                separator:遍历的两个对象中间所要拼接的串
                -->
                <!-- 使用实现下边的sql拼接
                and (id=1 or id=10 or id=16)
                 -->
                <foreach collection="ids" item="user_id" open="and (" close=")" separator="or">
                    <!--  每次遍历所需要拼接的串-->
                    id=#{user_id}
                </foreach>
            </if>

 

8.6.4     测试代码

 @Test
    public void testFindUserList() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建一个usermapper的对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建包装对象,设置查询条件
        UserQueryVo userQueryVo=new UserQueryVo();
        UserCustom userCustom=new UserCustom();
        
        //由于使用了动态sql,如果不设置某个值,这个条件不会拼接到sql中
        userCustom.setSex("1");
        userCustom.setUsername("小明");
        //传入多个id
        List <Integer> ids=new ArrayList<Integer>();
        ids.add(1);
        ids.add(10);
        ids.add(16);
        userQueryVo.setUserCustom(userCustom);
        //将ids传入statement中
        userQueryVo.setIds(ids);
        
        // 调用userMapper方法
        
        List<UserCustom> list = userMapper.findUserList(userQueryVo);
        //sqlSession.close();
        System.out.println(list.get(0).getUsername());

    }

 

8.6.5  另外一个sql的实现:

 

<!--实现  and id in(1,10,16)拼接  -->
                  <foreach collection="ids" item="user_id" open="  and id in(" close=")" separator=",">
                    <!--  每次遍历所需要拼接的串-->
                    #{user_id}
                </foreach>

 

posted @ 2016-05-26 19:25  破玉  阅读(438)  评论(0编辑  收藏  举报