MyBatis入门基础

一:对原生态JDBC问题的总结


新项目要使用mybatis作为持久层框架,由于本人之前一直使用的Hibernate,对mybatis的用法实在欠缺,最近几天计划把mybatis学习一哈,特将学习笔记记录于此,方便大家参考,也方便自己查阅。

  话不多说,先看看原始的JDBC程序代码,看看这样的代码存在什么问题

package com.utils;

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

/**
 * @ClassName: JdbcTest
 * @Description: TODO(原始的JDBC操作数据库)
 * @author warcaft
 * @date 2015-6-27 下午3:31:22
 *
 */
public class JdbcTest {
    public static void main(String[] args) {

        // 数据库连接
        Connection connection = null;
        // 预编译的Statement,使用预编译的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", "root");
            // 定义sql语句 ?表示占位符
            String sql = "select * from t_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();
                }
            }

        }

    }
}

二:MyBatis框架

1.MyBatis是什么?(下载地址:https://github.com/mybatis/mybatis-3/releases) 

   MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 

  MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

  Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

  2.MyBatis架构图

  

1、mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

 2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

 3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

 4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

 5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

 6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

 7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

三:mybatis入门程序

1.需求:(1).根据用户id(主键)查询用户信息 (2).根据用户名称模糊查询用户信息(3).添加用户 4).删除用户(5).更新用户

2.环境:java环境:JDK1.7,eclipse,Mysql5.1

3.工程目录结构

 

4.从mybatis的jar包结构可知mybatis用的是log4j记录日志,所以log4j.properties文件内容如下:

复制代码
# Global logging configuration
#在开发的环境下,日志级别要设置成DEBUG,生产环境设置成info或error
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
复制代码

5.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>
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
        <!-- 使用jdbc事务管理,事务控制由mybatis管理-->
            <transactionManager type="JDBC" />
        <!-- 数据库连接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
<!-- 加载映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
    </mappers>
</configuration>
复制代码

6.实体User.java内容

View Code

7.映射文件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">
<!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
    注意:使用mapper代理开发时,namespace有特殊作用
 -->
<mapper namespace="test">
<!-- 在映射文件中配置很多sql语句 -->
<!-- 需求:通过Id查询用户表的记录 -->
<!-- 通过SELECT执行数据库查询 
    id:标识映射文件中的sql,称为statement的id;
        将sql语句封装在mapperStatement的对象中,所以Id称为Statement的id;
    parameterType:指定输入参数的类型,这里指定int型
    #{}:表示一个占位符;
    #{id}:其中Id表示接收输入的参数,参数名称就是Id,如果输入参数是简单类型,#{}中的参数名可以任意,可以是value或者其它名称;
    resultType:指定sql输出结果所映射的java对象类型,select指定resultType表示将单条记录映射成java对象。
-->
<select id="findUserById" parameterType="int" resultType="com.mybatis.entity.User" >
    select * from t_user where id=#{id}
</select>
<!-- 根据用户名称模糊查询用户信息,可能返回多条数据
    resultType:指定的就是单条记录所映射的java类型;
    ${}:表示拼接sql字符串,将接收到的参数内容不加任何修饰拼接在sql中.
    使用${}拼接sql,可能会引起sql注入
    ${value}:接收输入参数的内容,如果传入的是简单类型,${}中只能使用value
 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.entity.User" >
    select * from t_user where username LIKE '%${value}%'
</select>
<!-- 添加用户 
parameterType:指定输入的参数类型是pojo(包括用户信息);
#{}中指定pojo的属性名称,接收到pojo对象的属性值    ,mybatis通过OGNL(类似struts2的OGNL)获取对象的属性值
-->
<insert id="insertUser" parameterType="com.mybatis.entity.User" >
    <!-- 
        将insert插入的数据的主键返回到User对象中;
        select last_insert_id():得到刚insert进去记录的主键值,只适用于自增主键;
        keyProperty:将查询到的主键值,设置到parameterType指定的对象的那个属性
        order:select last_insert_id()执行顺序,相对于insert语句来说它的执行顺序。
        resultType:指定select last_insert_id()的结果类型;
     -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select last_insert_id()
    </selectKey>
    <!-- 
        使用mysql的uuid(),实现非自增主键的返回。
        执行过程:通过uuid()得到主键,将主键设置到user对象的Id的属性中,其次,在insert执行时,从user对象中取出Id属性值;
     <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
        select uuid()
    </selectKey>
        insert into t_user (id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
     -->
    insert into t_user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 删除用户 
    根据ID删除用户,需要输入Id值
-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from t_user where id=#{id}
    </delete>
<!-- 更新用户 
    需要传入用户的Id和用户的更新信息
    parameterType:指定User对象,包括Id和用户的更新信息,注意:Id是必须存在的
    #{id}:从输入的User对象中获取Id的属性值
-->
<update id="updateUser" parameterType="com.mybatis.entity.User">
    update t_user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} 
    where id=#{id}
</update>

</mapper>
复制代码

8.测试程序MybatisService.java代码

复制代码
package com.mybatis.service;

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

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.Test;

import com.mybatis.entity.User;

/**
 * @ClassName: MybatisService
 * @Description: TODO(mybatis入门程序)
 * @author warcaft
 * @date 2015-6-27 下午4:49:49
 * 
 */
public class MybatisService {
    // 根据Id查询用户信息,得到一条记录结果
    @Test
    public void findUserByIdTest() {
        // mybatis的配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            // 1.创建会话工场,传入mybatis的配置文件信息
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(inputStream);

            // 2.通过工厂得到SqlSession
            sqlSession = sqlSessionFactory.openSession();

            // 3.通过sqlSession操作数据库
            // 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
            // 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
            // sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
            // selectOne:查询一条结果
            User user = sqlSession.selectOne("test.findUserById", 1);
            System.out.println(user.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 根据姓名模糊查询用户信息,得到一条或多条记录结果
    @Test
    public void findUserByNameTest() {
        // mybatis的配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            // 1.创建会话工场,传入mybatis的配置文件信息
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(inputStream);

            // 2.通过工厂得到SqlSession
            sqlSession = sqlSessionFactory.openSession();

            // 3.通过sqlSession操作数据库
            // 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
            // 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
            // sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
            // list中的user和resultType类型一致
            List<User> list = sqlSession.selectList("test.findUserByName", "小");
            System.out.println(list);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 添加用户
    @Test
    public void insertUserTest() {
        // mybatis的配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            // 1.创建会话工场,传入mybatis的配置文件信息
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(inputStream);
            // 2.通过工厂得到SqlSession
            sqlSession = sqlSessionFactory.openSession();
            //插入用户的对象
            User user = new User();
            user.setUsername("小红");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("上海");
            // 3.通过sqlSession操作数据库
            // 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
            // 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
            // sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
            sqlSession.insert("test.insertUser", user);
            //执行提交事务
            sqlSession.commit();
            
            //项目中经常需要 获取新增的用户的主键
            System.out.println(user.getId());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    // 根据Id删除用户
        @Test
        public void deleteUserTest() {
            // mybatis的配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = null;
            SqlSession sqlSession = null;
            try {
                inputStream = Resources.getResourceAsStream(resource);
                // 1.创建会话工场,传入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                        .build(inputStream);
                // 2.通过工厂得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 3.通过sqlSession操作数据库
                // 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
                // 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
                // sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
                //传入Id,删除用户
                sqlSession.delete("test.deleteUser", 7);
                //执行提交事务
                sqlSession.commit();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        
        // 根据Id更新用户信息
        @Test
        public void updateUserTest() {
            // mybatis的配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = null;
            SqlSession sqlSession = null;
            try {
                inputStream = Resources.getResourceAsStream(resource);
                // 1.创建会话工场,传入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                        .build(inputStream);
                // 2.通过工厂得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
                //更新用户的信息
                User user = new User();
                user.setId(2);
                user.setUsername("小黑");
                user.setBirthday(new Date());
                user.setSex("2");
                user.setAddress("上海");
                // 3.通过sqlSession操作数据库
                // 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
                // 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
                // sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
                //更具Id更新用户
                sqlSession.update("test.updateUser", user);
                //执行提交事务
                sqlSession.commit();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
}
复制代码

9.数据库所用sql脚本

复制代码
CREATE TABLE t_user (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(30) NOT NULL COMMENT '用户名称',
  birthday DATE DEFAULT NULL COMMENT '生日',
  sex CHAR(2) DEFAULT NULL COMMENT '性别',
  address VARCHAR(256) DEFAULT NULL COMMENT '地址'
);
INSERT INTO t_user (username,birthday,sex,address)
                                VALUES
                   ('小A','2015-06-27','2','北京'),
                   ('小B','2015-06-27','2','北京'),
                   ('小C','2015-06-27','1','北京'),
                   ('小D','2015-06-27','2','北京');
复制代码

四:mybatis和Hibernate的本质区别与应用场景

hibernate:是一个标准ORM框架(对象关系映射),入门门槛较高的,不需要程序写sqlsql语句自动生成了,对sql语句进行优化、修改比较困难的。

应用场景:

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

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

应用场景:

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

五:小结

1.parameterType和resultType

  parameterType:在映射文件中通过parameterType指定输入 参数的类型。

  resultType:在映射文件中通过resultType指定输出结果的类型

 2.#{}和${}

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

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

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

 

sql使

{};

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

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

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

3.selectOne()和selectList()

  selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。

  selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne

  如果使用selectOne报错: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

mybatis入门基础(二)----原始dao的开发和mapper代理开发

看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先苦后甜嘛!

一:原始dao开发方法

  概要:1.在上篇中搭建好的框价中编写dao接口和dao实现类

     2.向dao接口实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建sqlSession.

  • DAO接口类UserDAO.java  
复制代码
package com.mybatis.dao;
import java.util.List;
import com.mybatis.entity.User;
/**
 * 
 * @ClassName: UserDAO
 * @Description: TODO(用户管理DAO接口)
 * @author warcaft
 * @date 2015-6-27 下午10:23:42
 * 
 */
public interface UserDAO {
    /** 根据ID查询用户信息*/
    public User findUserById(Integer id);

    /**根据用户名称模糊查询用户信息*/
    public List<User>  findUserByName(String username);

    /** 添加用户*/
    public void insertUser(User user);

    /** 根据ID删除用户*/
    public void deleteUser(Integer id);

    /** 根据ID更新用户*/
    public void updateUser(User user);
}
复制代码
  • dao实现类UserDaoImpl.java 
复制代码
package com.mybatis.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.mybatis.entity.User;
/**
 * 
 * @ClassName: UserDaoImpl
 * @Description: TODO(用户管理接口的实现类)
 * @author warcaft
 * @date 2015-6-27 下午10:29:35
 * 
 */
public class UserDaoImpl implements UserDAO {
    private SqlSessionFactory sqlSessionFactory;
    // 需要向dao实现类中注入SqlSessionFactory
    // 通过构造方法注入
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

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

    @Override
    public List<User> findUserByName(String username) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession
                .selectList("test.findUserByName", username);

        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
        return list;
    }

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

    @Override
    public void deleteUser(Integer id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行插入操作
        sqlSession.delete("test.deleteUser", id);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }

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

}
复制代码
  • JunitTest测试UserDaoImplTest.java
复制代码
package com.mybatis.dao.test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
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.mybatis.dao.UserDaoImpl;
import com.mybatis.entity.User;

public class UserDaoImplTest {

    private SqlSessionFactory sqlSessionFactory;

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

    @Test
    public void findUserByIdTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = userDao.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void findUserByNameTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        List<User> list = userDao.findUserByName("小");
        System.out.println(list);
    }

    @Test
    public void insertUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = new User();
        user.setUsername("张三丰");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("武当山");
        userDao.insertUser(user);
    }

    @Test
    public void deleteUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        userDao.deleteUser(8);
    }

    @Test
    public void updateUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = new User();
        user.setId(1);
        user.setUsername("王六");
        user.setSex("2");
        user.setAddress("天津");
        user.setBirthday(new Date());
        userDao.updateUser(user);
    }
}
复制代码

才上面的代码可以看出,比起之前那个MybatisService.java类里面的内容稍微清晰了点吧。但依然存在以下几个问题:

  1.dao接口中存在大量模版方法,能否把这些代码提出来,减少我们的工作量

  2.调用sqlSession方法时将statement的id硬编码了

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

所以我们带着这几个问题看看mapper代理开发的方法,是否能解决这些问题呢?

二:mapper代理方法(只需要mapper接口,相当于dao接口)

1.概要:(1).编写XXXmapper.xml的映射文件

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

2.开发规范:

  (1).在XXXmapper.xml中namespace等于mapper接口地址;

  

      (2).XXXmapper.java接口中的方法和mapper.xml中的statement的Id一致。

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

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

  

  

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

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

3.UserMapper.java类代码

View Code

4.将原来的User.xml拷贝修改名称为UserMapper.xml,只需修改此行代码即可

<!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
    注意:使用mapper代理开发时,namespace有特殊作用,namespace等于mapper接口地址
 -->
<mapper namespace="com.mybatis.mapper.UserMapper">

5.在SqlMapConfig.xml中加载UserMapper.xml

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

6.Junit测试UserMapperTest.java

View Code

7.小结

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

  (2).mapper接口中的方法参数只能有一个是否影响系统开发:

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

  回答:系统框架中,dao层的代码是被业务层公用的。机试mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。

mybatis入门基础(三)----SqlMapConfig.xml全局配置文件解析

一:SqlMapConfig.xml配置文件的内容和配置顺序如下

  1. properties(属性)
  2. settings(全局配置参数)
  3. typeAiases(类型别名)
  4. typeHandlers(类型处理器)
  5. objectFactory(对象工厂)
  6. plugins(插件)
  7. environments(环境集合属性对象)mappers(映射器)
    1. environment(环境子属性对象)
    2. transactionManager(事物管理)
    3. datesource(数据源
  8. mappers(映射器)

二:properties属性

  作用:将数据连接单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值,在SqlMapConfig.xml中就不需要对数据库连接参数进行硬编码。数据库连接参数只配置在db.properties中,方便对参数进行统一管理,其它xml可以引用该db.properties。

db.properties的内容:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root

在SqlMapConfig.xml中加载db.properties

复制代码
 <!-- 加载数据库文件db.properties -->
<properties resource="db.properties">
        <!-- properties中还可以配置一些属性名和属性值,此处的优先加载 -->
        <!-- <property name="driver" value=""/> -->
    </properties>
    <!-- 和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>
复制代码

properties特性:

注意:

  • 在properties元素体内定义的属性优先读取。
  • 然后读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性。
  • 最后读取parameterType传递的属性,它会覆盖已读取的同名属性

建议:

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

  在properties文件中定义属性名要有一定的特殊性,如xxxx.xxxx(jdbc.driver)

三:settings全局参数配置

  mybatis框架运行时可以调整一些运行参数。比如,开启二级缓存,开启延迟加载等等。全局参数会影响mybatis的运行行为。

mybatis-settings的配置属性以及描述

setting(设置)Description(描述)valid Values(验证值组)Default(默认值)
cacheEnabled在全局范围内启用或禁用缓存配置 任何映射器在此配置下。true | falseTRUE
lazyLoadingEnabled在全局范围内启用或禁用延迟加载。禁用时,所有相关联的将热加载。true | falseTRUE
aggressiveLazyLoading启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。true | falseTRUE
multipleResultSetsEnabled允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。true | falseTRUE
useColumnLabel使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。true | falseTRUE
useGeneratedKeys允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。true | falseFALSE
autoMappingBehavior指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。

NONE,PARTIAL,FULL

PARTIAL
defaultExecutorType配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。

SIMPLE,REUSE,BATCH

SIMPLE
safeRowBoundsEnabled允许使用嵌套的语句RowBounds。true | falseFALSE
mapUnderscoreToCamelCase从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。true | falseFALSE
localCacheScopeMyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。

SESSION

STATEMENT

SESSION
dbcTypeForNull指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。JdbcType enumeration. Most common are: NULL, VARCHAR and OTHEROTHER
lazyLoadTriggerMethods指定触发延迟加载的对象的方法。A method name list separated by commasequals,clone,hashCode,toString
defaultScriptingLanguage指定所使用的语言默认为动态SQL生成。A type alias or fully qualified class name.

org.apache.ibatis.scripting.xmltags

.XMLDynamicLanguageDriver

callSettersOnNulls指定如果setter方法​​或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。true | falseFALSE
logPrefix指定的前缀字串,MyBatis将会增加记录器的名称。Any StringNot set
logImpl指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGINGNot set
proxyFactory指定代理工具,MyBatis将会使用创建懒加载能力的对象。CGLIB | JAVASSIST CGLIB

官方文档settings的例子

View Code

四:typeAiases(别名)--重点掌握

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

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

4.1.mybatis默认支持的别名

别名

映射的类型

_byte 

byte 

_long 

long 

_short 

short 

_int 

int 

_integer 

int 

_double 

double 

_float 

float 

_boolean 

boolean 

string 

String 

byte 

Byte 

long 

Long 

short 

Short 

int 

Integer 

integer 

Integer 

double 

Double 

float 

Float 

boolean 

Boolean 

date 

Date 

decimal 

BigDecimal 

bigdecimal 

BigDecimal 

 

4.2.自定义别名

  4.2.1:单个别名定义(在SqlMapConfig.xml)  

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

    UserMapper.xml引用别名:

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

  4.2.2:批量定义别名(常用) 

复制代码
<!-- 批量别名的定义:
        package:指定包名,mybatis会自动扫描包中的pojo类,自动定义别名,别名就是类名(首字母大写或小写都可以)
 -->
     <typeAliases>
         <package name="com.mybatis.entity"/>
         <package name="其它包"/>
    </typeAliases>
复制代码

五:typeHandlers(类型处理器)

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

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

mybatis支持类型处理器:

类型处理器

Java类型

JDBC类型

BooleanTypeHandler 

Boolean,boolean 

任何兼容的布尔值

ByteTypeHandler 

Byte,byte 

任何兼容的数字或字节类型

ShortTypeHandler 

Short,short 

任何兼容的数字或短整型

IntegerTypeHandler 

Integer,int 

任何兼容的数字和整型

LongTypeHandler 

Long,long 

任何兼容的数字或长整型

FloatTypeHandler 

Float,float 

任何兼容的数字或单精度浮点型

DoubleTypeHandler 

Double,double 

任何兼容的数字或双精度浮点型

BigDecimalTypeHandler 

BigDecimal 

任何兼容的数字或十进制小数类型

StringTypeHandler 

String 

CHAR和VARCHAR类型

ClobTypeHandler 

String 

CLOB和LONGVARCHAR类型

NStringTypeHandler 

String 

NVARCHAR和NCHAR类型

NClobTypeHandler 

String 

NCLOB类型

ByteArrayTypeHandler 

byte[] 

任何兼容的字节流类型

BlobTypeHandler 

byte[] 

BLOB和LONGVARBINARY类型

DateTypeHandler 

Date(java.util)

TIMESTAMP类型

DateOnlyTypeHandler 

Date(java.util)

DATE类型

TimeOnlyTypeHandler 

Date(java.util)

TIME类型

SqlTimestampTypeHandler 

Timestamp(java.sql)

TIMESTAMP类型

SqlDateTypeHandler 

Date(java.sql)

DATE类型

SqlTimeTypeHandler 

Time(java.sql)

TIME类型

ObjectTypeHandler 

任意

其他或未指定类型

EnumTypeHandler 

Enumeration类型

VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

六:mappers(映射配置)

6.1:通过resource加载单个映射文件

复制代码
<!-- 加载映射文件 -->
    <mappers>
    <!--通过resource方法一次加载一个映射文件  -->
        <mapper resource="sqlmap/User.xml"/>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
复制代码

6.2:通过mapper接口加载单个映射文件

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

按照上边的规范,将mapper.javamapper.xml放在一个目录 ,且同名。

6.3:批量加载mapper(推荐使用)

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

 

mybatis入门基础(四)----输入映射和输出映射

一:输入映射 

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

1.1.传递pojo的包装对象

 1.1.1.需求描述

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

 1.1.2.定义包装类型的pojo

    针对上边的需求,建议使用自定义的包装类型pojo,在包装类型的pojo中将复杂的查询条件包装进去。

包装查询条件的pojo类UserQueryVo类的代码:

View Code

 UserCustom类的代码

View Code

 UserMapper.xml的代码

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

View Code

UserMapper.java类的代码

View Code

Junit单元测试代码

View Code

二:输出映射

1.resultType

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

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

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

1.1.输出简单类型

   需求:用户信息的综合查询列表,通过查询总数才能实现分页功能。‘

   UserMapper.xml的代码 

复制代码
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
 6     注意:使用mapper代理开发时,namespace有特殊作用,namespace等于mapper接口地址
 7  -->
 8 <!-- 用户信息综合查询总数
 9      parameterType:指定输入类型,和findUserList一致。
10      resultType:输出结果类型.    
11   -->
12 <mapper namespace="com.mybatis.mapper.UserMapper">
13     <select id="findUserCount" parameterType="com.mybatis.entity.UserQueryVo" resultType="int">
14         select count(*) from t_user where  sex=#{userCustom.sex} and username like '%${userCustom.username}%'
15     </select>
16 </mapper>
复制代码

UserMapper.java的代码

1 public interface UserMapper {
2     //用户信息综合查询总数
3     public int findUserCount(UserQueryVo userQueryVo);
4 }

Junit测试代码

View Code

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

1.2.输出pojo对象和pojo列表   

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

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

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

1 public interface UserMapper {
2     /** 根据ID查询用户信息 */
3     public User findUserById(int id);
4 }

 1.2.2.输出pojo对象list,方法返回值是List<pojo>

1 public interface UserMapper {
2     /** 根据用户名称模糊查询用户信息 */
3     public List<User> findUserByName(String username);
4 }

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

1.3.输出类型resultMap

    mybatis中使用resultMap完成高级输出结果映射。

 1.3.1.resultMap使用方法

    (1).定义resultMap

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

 1.3.2.demo例子

  (1).需求:将下面的sql使用User完成映射

    select id id_,username username_ from t_user where id=?

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

  (2).定义resultMap   

复制代码
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2  <!DOCTYPE mapper
 3  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5   <!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
 6     注意:使用mapper代理开发时,namespace有特殊作用,namespace等于mapper接口地址
 7   -->
 8    <!-- 用户信息综合查询总数
 9      parameterType:指定输入类型,和findUserList一致。
10       resultType:输出结果类型.    
11    -->
12  <mapper namespace="com.mybatis.mapper.UserMapper">
13  <!-- 定义resultMap 
14      select id id_,username username_ from t_user和User类中的属性作为一个映射关系
15     type:resultMap最终映射的java对象类型,可以使用别名;
16      id:对resultMap的唯一标识
17  -->
18  <resultMap type="user" id="userResultMap">
19      <!--id表示查询结果中的唯一标识,
20          column:查询出来的列名
21          property:type指定的pojo类型中的属性名
22         最终resultMap对column和property作一个映射关系(对应关系)
23       -->
24      <id column="id_" property="id"/>
25      <!--result:表示对普通列名的映射,
26         column:查询出来的列名
27        property:type指定的pojo类型中的属性名
28          最终resultMap对column和property作一个映射关系(对应关系)
29        -->
30      <result column="username_" property="username"/>
31  </resultMap>
32  </mapper>
复制代码

 

  (3).使用resultMap作为statement的输出类型映射

复制代码
1 <!-- 使用resultMap作为输出映射
2     resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper.xml文件中,前边需要添加namespace命名空间
3  -->
4 <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap" >
5     select id id_,username username_ from t_user where id=#{id}
6 </select>
复制代码

UserMapper.java代码

public interface UserMapper {

    /** 根据ID查询用户信息,使用resultMap进行输出 */
    public User findUserByIdResultMap(int id);
}

Junit测试代码:

View Code

小结:

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

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

mybatis入门基础(五)----动态SQL

一:动态SQL

  1.1.定义

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

  1.2.案例需求

    用户信息综合查询列表这个statement的定义使用动态sql,对查询条件进行判断,如果输入参数不为空才进行查询拼接。

  1.3.UserMapper.xml

复制代码
 1 <!-- 用户信息综合查询 
 2     #{userCustom.sex}:取出pojo包装对象中性别值
 3     ${userCustom.username}:取出pojo对象中用户名称
 4 -->
 5     <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo" 
 6     resultType="com.mybatis.entity.UserCustom">
 7         select * from t_user 
 8         <!-- 动态sql查询:where可以自动去掉第一个and -->
 9         <where>
10             <if test="userCustom!=null">
11                 <if test="userCustom.sex!=null and userCustom.sex!='' ">
12                     and sex=#{userCustom.sex}
13                 </if>
14                 <if test="userCustom.username!=null and userCustom.username!='' ">
15                     and username=#{userCustom.username}
16                 </if>
17             </if>
18         </where>
19 <!--          where sex=#{userCustom.sex} and username LIKE '%${userCustom.username}%' -->
20     </select>
复制代码

  1.4.测试代码

复制代码
 1     @Test
 2     public void testFindUserList() {
 3         SqlSession sqlSession = sqlSessionFactory.openSession();
 4         //创造查询条件
 5         UserQueryVo userQueryVo = new UserQueryVo();
 6         UserCustom userCustom = new UserCustom();
 7 //        userCustom.setSex("2");
 8         //这里使用动态sql,如果不设置某个值,条件不会拼接sql中
 9         userCustom.setUsername("小");
10         userQueryVo.setUserCustom(userCustom);
11         // 创建Usermapper对象,mybatis自动生成mapper代理对象
12         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
13         List<UserCustom>list=mapper.findUserList(userQueryVo);
14         //测试动态sql,属性的非空判断测试
15 //        List<UserCustom>list=mapper.findUserList(null);
16         System.out.println(list);
17         sqlSession.commit();
18         sqlSession.close();
19     }
复制代码

二:SQL片段

  2.1.需求

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

  2.2.定义sql片段  

复制代码
 1 <!-- 定义sql片段,Id是唯一标识
 2          建议:是基于单表来定义sql片段,这样的话sql片段的可重用性才高,在sql片段中不要包含where
 3      -->
 4     <sql id="query_user_where" >
 5         <if test="userCustom!=null">
 6                 <if test="userCustom.sex!=null and userCustom.sex!='' ">
 7                     and sex=#{userCustom.sex}
 8                 </if>
 9                <if test="userCustom.username!=null and userCustom.username!='' ">
10                     and username=#{userCustom.username}
11                 </if>
12             </if>
13     </sql>
复制代码

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

复制代码
 1 <!-- 用户信息综合查询 
 2     #{userCustom.sex}:取出pojo包装对象中性别值
 3     ${userCustom.username}:取出pojo对象中用户名称
 4 -->
 5     <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo" 
 6     resultType="com.mybatis.entity.UserCustom">
 7         select * from t_user 
 8         <!-- 动态sql查询:where可以自动去掉第一个and -->
 9         <where>
10         <!-- 引用sql片段的id,如果refid指定的不在本mapper.xml中,需要前边加namespace -->
11             <include refid="query_user_where"></include>
12             <!-- 这里可以引用其它的sql片段 -->
13         </where>
14     </select>
复制代码

三:foreach

  作用:向sql传递数组或者list,mybatis使用foreach解析

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

3.1.需求

  sql语句如下:

  两种方法:

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

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

3.2.在输入参数包装类型中添加List<Integer> ids 传入多个id

复制代码
 1 package com.mybatis.entity;
 2 
 3 import java.util.List;
 4 
 5 /**
 6  * 
 7  * @ClassName: UserQueryVo
 8  * @Description: TODO(包装类型)
 9  * @author warcaft
10  * 
11  */
12 public class UserQueryVo {
13 
14     public List<Integer> ids;
15 
16     public List<Integer> getIds() {
17         return ids;
18     }
19 
20     public void setIds(List<Integer> ids) {
21         this.ids = ids;
22     }
23 }
复制代码

3.3.mapper.xml代码

复制代码
 1     <!-- 实现下边的sql拼接
 2             select * from t_user where id=1 OR id=2 OR id=3
 3     -->
 4     <select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo" 
 5     resultType="com.mybatis.entity.User">
 6             select * from t_user
 7         <where>
 8                 <if test="ids!=null">
 9                 <!-- 使用foreach遍历ids
10                     collection:指定输入对象的集合属性
11                     item:每个遍历生成对象中
12                     open:开始遍历时拼接的串
13                     close:技术遍历时拼接的串
14                     separator:遍历的两个对象中需要拼接的串
15                  -->
16                 <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
17                     id=#{user_id}
18                 </foreach>
19             </if>
20         </where>
21     </select>
复制代码
select * from t_user where id in(1,2,3)的mapper.xml配置
复制代码
 1  <select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo" 
 2     resultType="com.mybatis.entity.User">
 3             select * from t_user
 4         <where>
 5                 <if test="ids!=null">
 6                 <!-- 
 7                     使用foreach遍历ids
 8                     collection:指定输入对象的集合属性
 9                     item:每个遍历生成对象中
10                     open:开始遍历时拼接的串
11                     close:技术遍历时拼接的串
12                     separator:遍历的两个对象中需要拼接的串
13                  -->
14                 <!-- 实现“ select * from t_user where  id in(1,2,3)”拼接 -->
15                 <foreach collection="ids" item="user_id" open="AND id in ("  close=")" separator=",">
16                     id=#{user_id}
17                 </foreach>
18             </if>
19         </where>
20     </select>
复制代码

userMapper.java代码

1 public interface UserMapper {
2     //ids查询用户数据
3     public List<User> findUserByIds(UserQueryVo userQueryVo);
4 }

Junit测试代码

复制代码
 1 @Test
 2     public void findUserByIdsTest() {
 3         SqlSession sqlSession = sqlSessionFactory.openSession();
 4         // 创建Usermapper对象,mybatis自动生成mapper代理对象
 5         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
 6         //创造查询条件
 7         UserQueryVo userQueryVo = new UserQueryVo();
 8         //传入多个id
 9         List<Integer> ids=new ArrayList<Integer>();
10         ids.add(1);
11         ids.add(2);
12         ids.add(3);
13         //将ids通过userQueryVo传入statement中
14         userQueryVo.setIds(ids);
15         //调用userMapper的代码
16         List<UserCustom> userList= mapper.findUserList(userQueryVo);
17         System.out.println(userList);
18         sqlSession.close();
19     }
以上总结的很全面,多谢原创


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值