(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

MyBatis基础知识

文章目录

  • MyBatis基础知识
    • 1.对原生态JDBC程序(单独使用JDBC开发)问题总结
      • 1.1环境
      • 1.2创建mysql数据
      • 1.3jdbc程序
      • 1.4问题总结
    • 2.mybatis框架原理
      • 2.1mybatis是什么?
      • 2.2mybatis框架
    • 3.mybatis入门程序
      • 3.1需求
      • 3.2环境
      • 3.3log4j.properties
      • 3.4工程结构
      • 3.5SqlMapConfig.xml
      • 3.6. 根据用户id(主键)查询用户信息
        • 3.6.1创建po类
        • 3.6.2映射文件
        • 3.6.3在SqlMapConfig.xml中加载映射文件
        • 3.6.4程序编写
      • 3.7根据用户名称模糊查询用户信息
        • 3.7.1映射文件
        • 3.7.2程序代码
      • 3.8添加用户
        • 3.8.1映射文件
        • 3.8.2程序代码
      • 3.9删除用户
        • 3.9.1映射文件
        • 3.9.2程序代码
      • 3.10更新用户
        • 3.10.1映射文件
        • 3.10.2程序代码
      • 3.11总结
        • 3.11.1parameterType
        • 3.11.2resultType
        • 3.11.3#{}和${}
        • 3.11.4selectOne和selectList
      • 3.12 mybatis和hibernate本质区别和应用场景
        • 3.12.1hibernate
        • 3.12.2 mybatis
    • 4.mybatis开发dao两种方法
      • 4.1SqlSession使用范围
        • 4.1.1SqlSessionFactoryBuilder
        • 4.1.2SqlSessionFactory
        • 4.1.3 SqlSession
      • 4.2原始dao开发方法(程序需要编写dao接口和dao实现类)
        • 4.2.1思路
        • 4.2.2dao接口
        • 4.2.3接口实现类
        • 4.2.4测试代码
        • 4.2.5总结原始 dao开发问题
      • 4.3mybatis的mapper接口(相当于dao接口)代理开发方法
        • 4.3.1思路(mapper代理开发规范)
        • 4.3.2mapper.java
        • 4.3.3mapper.xml
        • 4.3.4在SqlMapConfig中加载mapper.xml
        • 4.3.5测试
      • 4.3.6一些问题总结
        • 4.3.6.1代理对象内部调用selectOne或selectList
        • 4.3.6.2mapper接口方法参数只能有一个是否影响系统开发
    • 5.mybatis配置文件SqlMapConfig.xml
      • 5.1properties属性
      • 5.2settings全局参数配置
      • 5.3 typeAliases(别名)重点
        • 5.3.1需求
        • 5.3.2mybatis默认支持别名
        • 5.3.3自定义别名
          • 5.3.3.1单个别名定义
          • 5.3.3.2批量定义别名(常用)
      • 5.4typeHandlers(类型处理器)
      • 5.5mappers(映射配置)
        • 5.5.1通过resource加载单个映射文件
        • 5.5.2通过mapper接口加载单个mapper
        • 5.5.3批量加载mapper(推荐使用)
    • 6.输入映射
      • 6.1传递pojo的包装对象
        • 6.1.1需求
        • 6.1.2定义包装类型pojo
        • 6.1.3mapper.xml
        • 6.1.4mapper.java
        • 6.1.5测试代码
    • 7.输出映射
      • 7.1resultType
      • 7.1.1输出简单类型
        • 7.1.1.1需求
        • 7.1.1.2mapper.xml
        • 7.1.1.3mapper.java
        • 7.1.1.4测试代码
        • 7.1.1.5小结
      • 7.1.2输出pojo对象和pojo列表
      • 7.2 resultMap
        • 7.2.1 resultMap使用方法
        • 7.2.2 将下边的sql使用User完成映射
          • 7.2.2.1定义reusltMap
          • 7.2.2.2使用resultMap作为statement的输出映射类型
          • 7.2.2.3mapper.java
          • 7.2.2.4测试代码
      • 7.3小结
    • 8.动态sql
      • 8.1什么是动态sql
      • 8.2需求
      • 8.3mapper.xml
      • 8.4测试代码
      • 8.5 sql片段
        • 8.5.1需求
        • 8.5.2定义sql片段
        • 8.5.3引用sql片段
        • 8.5.4测试代码
      • 8.6foreach
        • 8.6.1 需求
        • 8.6.2 在输入参数类型中添加属性传入多个id
        • 8.6.3修改mapper.xml
        • 8.6.4测试代码
        • 8.6.5另外一个sql片段
    • 9.打赏鼓励
      • 9.1微信打赏
      • 9.2支付宝打赏

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

1.1环境

java环境:jdk1.7.0_72
eclipse:indigo
mysql:5.1

1.2创建mysql数据

导入下边的脚本:
sql_table.sql:记录表结构
sql_data.sql:记录测试数据,在实际企业开发中,最后提供一个初始化数据脚本

1.3jdbc程序

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

(2)创建java工程,加入jar包:

(3)数据库驱动包(mysql-5.7.21)

上边的是mysql驱动。
下边的是oracle的驱动。

(4)程序代码:

package com.gdc.gengducun.jdbc;import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;public class JdbcTest {public static void main(String[] args) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {//加载数据库驱动Class.forName("com.mysql.jdbc.Driver");//通过驱动管理类获取数据库链接connection =  (Connection) DriverManager.getConnection("jdbc:mysql://47.104.10.229:3306/mybatis?characterEncoding=utf-8&useSSL=false", "xiongjie", "x_iongjie_sz_88");//定义sql语句 ?表示占位符String sql = "select * from user where username = ?";//获取预处理statementpreparedStatement = (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) {e.printStackTrace();}}if(preparedStatement!=null){try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}}

1.4问题总结

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

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

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

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

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

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

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

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

2.mybatis框架原理

2.1mybatis是什么?

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

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

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

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

2.2mybatis框架


(1)SqlMapConfig.xml:是mybatis的全局配置文件,名称是不固定的。
里面需要配置什么呢?

  • 数据源,使用第三方的连接池
  • 事务,用spring的
  • 等mybatis运行环境

mybatis自己需要做的事情是配置映射关系

  • mapper.xml(称为映射文件)
  • 这个配置文件里面主要配置的是sql语句

(2)SqlSessionFactory(会话工厂),根据配置文件创建工厂。
作用:创建SqlSession

(3)SqlSession(会话),是一个接口中,一个面向用户(程序员)的接口。
作用:用于操作数据库(发出sql,增、删、改、查)

(4)Executor(执行器),是一个接口,有两个实现

  • 一个是基本执行器
  • 一个是缓存执行器

作用:SqlSession内部通过执行器操作数据库

(5)mapped statement(底层封装对象)
作用:对操作数据库存储封装,包括sql语句,输入参数,输出结果类型。

(6)输入的参数类型

  • java简单类型
  • HashMap
  • pojo自定义类型

(7)输出的结果类型

  • java简单类型
  • HashMap
  • pojo自定义类型

3.mybatis入门程序

3.1需求

根据用户id(主键)查询用户信息
根据用户名称模糊查询用户信息
添加用户
删除 用户
更新用户

3.2环境

java环境:jdk1.7.0_72
eclipse:indigo
mysql:5.1

mybatis运行环境(jar包):
从https://github.com/mybatis/mybatis-3/releases下载,3.2.7版本

lib下:依赖包
mybatis-3.2.7.jar:核心包
mybatis-3.2.7.pdf,操作指南

加入mysql的驱动包

3.3log4j.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

mybatis默认使用log4j作为输出日志信息。

3.4工程结构

3.5SqlMapConfig.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="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://47.104.10.229:3306/mybatis?characterEncoding=utf-8" /><property name="username" value="xiongjie" /><property name="password" value="x_iongjie_sz_88" /></dataSource></environment></environments></configuration>

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

3.6.1创建po类

(1)属性名与数据库字段对应的类

package com.gdc.virtualstall.po;import java.util.Date;/*** 用户po*/
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;}@Overridepublic String toString() {return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]";}}

3.6.2映射文件

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

(2)在映射文件中配置sql语句。

  • Hibernate中叫做ORM对象关系映射,可以简单理解为就是把Java与关系数据库的二维表之间进行映射。
  • 而在mybatis中具体化了,有输入映射与输出映射。

(3)在classpath下的sqlmap目录下创建sql映射文件Users.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">
<!--
1.namespace命名空间,作用就是对sql进行分类化的管理,理解为sql的一个隔离
2.注意:使用mapper代理的方法开发,这个namespace就有特殊的重要作用。
-->
<mapper namespace="test"><!--
3.需求:根据用户id(主键)查询用户信息4.在映射文件中需要配置很多的sql语句4.1通过select来进行查询4.2id是用于标识映射文件中的sql,这个id可以称之为sql的id,但有一个比较专业的说法是statement的id.4.3将来sql语句会封装到mappedStatement对象中,所以将id称为statement的id。4.4#{}表示一个占位符号4.5parameterType:用于指定参数的类型,这里指定int型,是因为数据库里的id字段的数据类型为int型4.6#{id}其中的id表示接收输入的参数,参数的名称就是id,如果输入类型是简单类型,#{}中的参数名称可以任意。
可以是value或者是其他的名称4.7resultType:用于指定sql输出结果所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。--><select id="findUserById" parameterType="int" resultType="com.gdc.virtualstall.po.User">SELECT * FROM user WHERE id = #{id};
</select></mapper>

namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。

3.6.3在SqlMapConfig.xml中加载映射文件

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

3.6.4程序编写

package com.gdc.virtualstall.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 org.junit.Test;import com.gdc.virtualstall.po.User;/*** 入门程序*/
public class MyBatisFirst {//根据id查询用户的信息,得到一条记录结果@Testpublic void findUserByIdTest() throws IOException{//s0.mybatis配置文件String resource = "SqlMapConfig.xml";//s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//s3.通过工厂得到SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();/** s4.通过SqlSession操作数据库* s4.1第一个参数statement:映射文件中statement的id,=namespace+"."+statement的id* s4.2第一个参数parameter:指定和映射文件中所匹配的parameterType类型的参数* s4.3sqlSession.selectOne的结果是与映射文件中所匹配的resultType类型的对象*/User user = sqlSession.selectOne("test.findUserById", 1);System.out.println(user);//s5.释放会话资源sqlSession.close();}
}

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

3.7.1映射文件

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

<!--
1.根据用户名称模糊查询用户信息
2.可能返回多条
3.resultType:指定的就是单条记录所映射的java对象类型
4.${}:表示拼接字符串,将接收到的参数的内容不加任何修饰拼接在sql中
5.使用${}来拼字sql,可能会引起sql注入
6.${value}:表示接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value,-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.gdc.virtualstall.po.User">
SELECT * FROM user WHERE username LIKE '%${value}%';
</select>

3.7.2程序代码

 /*** 根据用户名称模糊查询用户信息* @throws IOException */@Testpublic void findUserByName() throws IOException{//s0.mybatis配置文件String resource = "SqlMapConfig.xml";//s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//s3.通过工厂得到SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//s4.list中的User和映射文件中resultType所指定的类型一致List<User> list = sqlSession.selectList("test.findUserByName", "小明");System.out.println(list);//s5.释放会话资源sqlSession.close();}

3.8添加用户

3.8.1映射文件

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

<!--
3.添加用户
3.1parameterType:指定输入参数类型是pojo(包括用户信息)
3.2#{}中指定pojo的属性名称,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值.--><insert id="insertUser" parameterType="com.gdc.virtualstall.po.User">insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})</insert>

3.8.2程序代码

 /*** 添加用户信息* @throws IOException*/@Testpublic void insertUserTest() throws IOException{//s0.mybatis配置文件String resource = "SqlMapConfig.xml";//s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//s3.通过工厂得到SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//s4.插入用户对象User user = new User();user.setUsername("王小军");user.setBirthday(new Date());user.setSex("1");user.setAddress("湖北恩施");int ret = sqlSession.insert("test.insertUser", user);System.out.println(ret);//s5.提交事务sqlSession.commit();//s6.释放会话资源sqlSession.close();}

3.9删除用户

3.9.1映射文件

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

3.9.2程序代码

 /*** 删除用户信息* @throws IOException*/@Testpublic void deleteUserTest() throws IOException{//s0.mybatis配置文件String resource = "SqlMapConfig.xml";//s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//s3.通过工厂得到SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//s4.传入id删除用户int ret = sqlSession.delete("test.deleteUser", 28);System.out.println(ret);//s5.提交事务sqlSession.commit();//s6.释放会话资源sqlSession.close();}

3.10更新用户

3.10.1映射文件

<!--
5.更新用户
5.1根据id更新用户,需要传入用户id,用户的更新信息
5.2parameterType来指定User对象,包括id和更新信息,注意id是必须存在
5.3#{id}:从输入的User对象中获取id的属性值
-->
<update id="updateUser" parameterType="com.gdc.virtualstall.po.User">update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>

3.10.2程序代码

/*** 添加用户信息* @throws IOException*/@Testpublic void updateUserTest() throws IOException{//s0.mybatis配置文件String resource = "SqlMapConfig.xml";//s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//s3.通过工厂得到SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();/** s4.更新用户的信息* s4.1必须要设置id*/User user = new User();user.setId(27);user.setUsername("王大军");user.setBirthday(new Date());user.setSex("2");user.setAddress("湖北恩施");int ret = sqlSession.update("test.updateUser", user);System.out.println(ret);//s5.提交事务sqlSession.commit();//s6.释放会话资源sqlSession.close();}

3.11总结

3.11.1parameterType

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

3.11.2resultType

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

3.11.3#{}和${}

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

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

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

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

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

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

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

3.11.4selectOne和selectList

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

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

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

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

3.12.1hibernate

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

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

(3)应用场景:

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

3.12.2 mybatis

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

(2)应用场景:

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

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

4.mybatis开发dao两种方法

4.1SqlSession使用范围

4.1.1SqlSessionFactoryBuilder

(1)通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory

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

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

4.1.2SqlSessionFactory

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

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

4.1.3 SqlSession

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

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

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

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

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

4.2.1思路

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

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

4.2.2dao接口

package com.gdc.virtualstall.dao;import java.util.List;import com.gdc.virtualstall.po.User;public interface IUserDao {// s1.根据id查询用户信息public User findUserById(int id) throws Exception;// s2.根据用户的名称查询用户的列表public List<User> findUserByName(String name) throws Exception;// s3.添加用户信息public void insertUser(User user) throws Exception;// s4.删除用户信息public void deleteUser(int id) throws Exception;}

4.2.3接口实现类

package com.gdc.virtualstall.dao.impl;import java.util.List;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;import com.gdc.virtualstall.dao.IUserDao;
import com.gdc.virtualstall.po.User;/*** s1.需要在实现类中注入SqlSessionFactory s2.此处通过构造参数注入*/
public class UserDaoImpl implements IUserDao {private SqlSessionFactory sqlSessionFactory;public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic User findUserById(int id) throws Exception {// s1.为了保证线程安全,将SqlSession的创建放在方法中SqlSession sqlSession = sqlSessionFactory.openSession();User user = sqlSession.selectOne("test.findUserById", id);// s2.释放资源sqlSession.close();return user;}@Overridepublic List<User> findUserByName(String name) throws Exception {// s1.为了保证线程安全,将SqlSession的创建放在方法中SqlSession sqlSession = sqlSessionFactory.openSession();List<User> userList = sqlSession.selectList("test.findUserByName", name);// s2.释放资源sqlSession.close();return userList;}@Overridepublic void insertUser(User user) throws Exception {// s1.为了保证线程安全,将SqlSession的创建放在方法中SqlSession sqlSession = sqlSessionFactory.openSession();// s2.插入用户对象int ret = sqlSession.insert("test.insertUser", user);System.out.println(ret);// s3.提交事务sqlSession.commit();// s4.释放会话资源sqlSession.close();}@Overridepublic void deleteUser(int id) throws Exception {// s1.为了保证线程安全,将SqlSession的创建放在方法中SqlSession sqlSession = sqlSessionFactory.openSession();// s2.删除用户对象int ret = sqlSession.delete("test.deleteUser", 27);System.out.println(ret);// s3.提交事务sqlSession.commit();// s4.释放会话资源sqlSession.close();}}

4.2.4测试代码

package com.gdc.virtualstall.dao.impl;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.gdc.virtualstall.dao.IUserDao;
import com.gdc.virtualstall.po.User;public class UserDaoImplTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUp() throws Exception {// 创建SqlSessionFactory// s0.mybatis配置文件String resource = "SqlMapConfig.xml";// s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception {// s1.创建IUserDao接口的对象IUserDao userDao = new UserDaoImpl(sqlSessionFactory);// s2.调用IUserDao接口的方法User user = userDao.findUserById(1);System.out.println(user);}}

4.2.5总结原始 dao开发问题

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

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

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

4.3mybatis的mapper接口(相当于dao接口)代理开发方法

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

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

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

(3)开发规范:

  • 在mapper.xml中namespace等于mapper接口地址
<!--
1.namespace命名空间,作用就是对sql进行分类化的管理,理解为sql的一个隔离
2.注意:使用mapper代理的方法开发,这个namespace就有特殊的重要作用,namespace等于mapper接口地址
-->
<mapper namespace="com.gdc.virtualstall.mapper.IUserMapper">
  • mapper.java接口中的方法名和mapper.xml中statement的id一致。

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

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

 // s1.根据id查询用户信息public User findUserById(int id) throws Excep tion;
<select id="findUserById" parameterType="int" resultType="com.gdc.virtualstall.po.User">SELECT * FROM user WHERE id = #{value}
</select>

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

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

4.3.2mapper.java

package com.gdc.virtualstall.mapper;
import com.gdc.virtualstall.po.User;public interface IUserMapper {// s1.根据id查询用户信息public User findUserById(int id) throws Exception;/*// s2.根据用户的名称查询用户的列表public List<User> findUserByName(String name) throws Exception;// s3.添加用户信息public void insertUser(User user) throws Exception;// s4.删除用户信息public void deleteUser(int id) throws Exception;*/}

4.3.3mapper.xml

<select id="findUserById" parameterType="int" resultType="com.gdc.virtualstall.po.User">SELECT * FROM user WHERE id = #{value}
</select>

4.3.4在SqlMapConfig中加载mapper.xml

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

4.3.5测试

package com.gdc.virtualstall.mapper.impl;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.gdc.virtualstall.mapper.IUserMapper;
import com.gdc.virtualstall.po.User;public class IUserMapperTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUp() throws Exception {// 创建SqlSessionFactory// s0.mybatis配置文件String resource = "SqlMapConfig.xml";// s1.得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// s2.创建会话工厂SqlSessionFactory,传入mybatis的配置文件信息this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception {//s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();//s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);//s3.调用IUserMapper的方法User user = userMapper.findUserById(1);System.out.println(user);}}

4.3.6一些问题总结

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

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

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

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

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

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

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

(4)注意:持久层方法的参数可以包装类型、map。。。,service方法中建议不要使用包装类型(不利于业务层的可扩展)。
因为service是被很多前台客户端去调用的,如果写成一个包装的内型,这样是不利于业务层的扩展性。

5.mybatis配置文件SqlMapConfig.xml

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

  • properties(属性)
  • settings(全局配置参数)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境集合属性对象)
  • environment(环境子属性对象)
  • transactionManager(事务管理)
  • dataSource(数据源)
  • mappers(映射器)

5.1properties属性

(1)需求

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

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

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

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://47.104.10.229:3306/mybatis?characterEncoding=utf-8
jdbc.username=xiongjie
jdbc.password=x_iongjie_sz_88

(2)在sqlMapConfig.xml加载属性文件:

 <!-- s0.加载属性文件 --><properties resource="db.properties"></properties><!-- s1.和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>

(3)properties特性:

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

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

建议:

  • 不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
  • 在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

5.2settings全局参数配置

(1)mybatis框架在运行时可以调整一些运行参数。
比如:开启二级缓存、开启延迟加载。。

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

(3)详细参见“学习资料/mybatis-settings.xlsx”文件

5.3 typeAliases(别名)重点

5.3.1需求

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

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

5.3.2mybatis默认支持别名

别名 映射的类型
_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

5.3.3自定义别名

5.3.3.1单个别名定义
        <!--s2.1针对单个别个别名的定义type:类型的路径alias:别名--><typeAlias type="com.gdc.virtualstall.po.User" alias="user"/>

引用别名:


<select id="findUserById" parameterType="int" resultType="User">SELECT * FROM user WHERE id = #{value}
</select>
5.3.3.2批量定义别名(常用)
     <!-- s2.2批量别名的定义指定包名,mybatis会自动的扫描包中的po类,自动定义别名,别名是什么呢?别名就是类名,(首字母大小或小写都可以)--><package name="com.gdc.virtualstall.po"/>

5.4typeHandlers(类型处理器)

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

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

(3)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-任何兼容的字符串类型,作为代码存储(而不是索引)。

5.5mappers(映射配置)

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

 <!-- s2.加载映射文件 --><mappers><mapper resource="sqlmap/User.xml"/><!-- 通过resource一次加载一个文件 --><mapper resource="mapper/UserMapper.xml"/></mappers>

5.5.2通过mapper接口加载单个mapper

     <!-- s2.通过mapper接口来加载映射文件s2.1需要遵循一些规范:(1)需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录。(2)前提是使用的是mapper代理的方法--><mapper class="com.gdc.virtualstall.mapper.IUserMapper"/>

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

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

6.输入映射

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

6.1传递pojo的包装对象

6.1.1需求

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

6.1.2定义包装类型pojo

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

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

package com.gdc.virtualstall.vo;import com.gdc.virtualstall.po.UserCustom;/*** 1.用户包装类型* 1.1为什么是叫VO呢?VO表示的是视图层面的对象,而PO指的是持久层的对象,POJO指的是自定义的类似于PO与VO综合体之间的javabean* 1.2在这个类中包装所需要的查询条件* 1.3可以通过组合的方式添加很多的属性。*/
public class UserQueryVo {//s1.用户的查询条件private UserCustom userCustom;public UserCustom getUserCustom() {return userCustom;}public void setUserCustom(UserCustom userCustom) {this.userCustom = userCustom;}//s2.可以包装其它的查询条件,订单、商品
}

6.1.3mapper.xml

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

<!-- 6.用户信息的综合查询 6.1#{userCustom.sex},用于取出包装对象中性别的值6.2${userCustom.username},用于取出包装对象中用户的名称6.3输出结果的信息,包含用户的信息,有可能除了用户信息还有其他的信息,后面还会加入一些子查询,这个子查询加入进去之后,就有可能没有属性与之对应了。所以将自定义的userCustom作为
-->
<select id="findUserList" parameterType="com.gdc.virtualstall.vo.UserQueryVo" resultType="com.gdc.virtualstall.po.UserCustom">select * from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'
</select>

6.1.4mapper.java

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

6.1.5测试代码

 /*** 用户信息的综合查询* @throws Exception*/@Testpublic void testFindUserList() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.创建包装对象,设置查询条件UserQueryVo userQueryVo = new UserQueryVo();UserCustom userCustom = new UserCustom();userCustom.setSex("1");userCustom.setUsername("张三丰");userQueryVo.setUserCustom(userCustom);// s4.调用IUserMapper的方法List<UserCustom> userCustomList = userMapper.findUserList(userQueryVo);System.out.println(userCustomList);}

7.输出映射

7.1resultType

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

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

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

7.1.1输出简单类型

7.1.1.1需求

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

7.1.1.2mapper.xml

<!-- 7.用户信息的综合查询总数7.1parameterType:指定的输入类型和findUserList一样7.2resultType:输出的结果类型--><select id="findUserCount" parameterType="com.gdc.virtualstall.vo.UserQueryVo" resultType="int">select count(*) from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'</select>

7.1.1.3mapper.java

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

7.1.1.4测试代码

7.1.1.5小结

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

7.1.2输出pojo对象和pojo列表

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

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

  • 输出单个pojo对象,方法返回值是单个对象类型
 // s1.根据id查询用户信息public User findUserById(int id) throws Exception;
  • 输出pojo对象list,方法返回值是
List<Pojo>
 // s2.根据用户的名称查询用户的列表public List<User> findUserByName(String name) throws Exception;

(3)生成的动态代理对象中是根据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 type="user" id="userResultMap"><!-- 8.3id表示的是查询结果集中唯一的标识 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的输出映射类型
<!--9.使用resultMap进行输出映射resultMap:指定定义resultMap的id,如果这个resultMap在其他的mapper文件,前边需要加namespace.--><select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">SELECT id id_,username username_ FROM user WHERE id = #{value}
</select>
7.2.2.3mapper.java
 // s7.根据id查询用户信息,使用resultMap输出public User findUserByIdResultMap(int id) throws Exception;
7.2.2.4测试代码
 @Testpublic void testFindUserByIdResultMap() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.调用IUserMapper的方法User user = userMapper.findUserByIdResultMap(1);System.out.println(user);}

7.3小结

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

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

8.动态sql

8.1什么是动态sql

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

8.2需求

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

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

8.3mapper.xml

<!-- 7.用户信息的综合查询总数7.1parameterType:指定的输入类型和findUserList一样7.2resultType:输出的结果类型--><select id="findUserCount" parameterType="com.gdc.virtualstall.vo.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="user.username!=null and user.username!=''">and user.username like '%${userCustom.username}%'</if></if></where>  </select>

8.4测试代码

 /*** 用户信息的综合查询* @throws Exception*/@Testpublic void testFindUserList() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.创建包装对象,设置查询条件UserQueryVo userQueryVo = new UserQueryVo();UserCustom userCustom = new UserCustom();// s4由于使用动态sql,如果不设置某个值,条件不会拼接在sql中 //userCustom.setSex("1");//userCustom.setUsername("张三丰");userQueryVo.setUserCustom(userCustom);// s4.调用IUserMapper的方法List<UserCustom> userCustomList = userMapper.findUserList(null);System.out.println(userCustomList);}

8.5 sql片段

8.5.1需求

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

(2)方便程序员进行开发。

8.5.2定义sql片段

<!-- 10.定义sql片段10.1id:sql片段的唯一标识10.2经验:(1)是基于单表来进行定义的,这样的话,这个sql片段的可重用性才高(2)在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片段:

<!-- 6.用户信息的综合查询 6.1#{userCustom.sex},用于取出包装对象中性别的值6.2${userCustom.username},用于取出包装对象中用户的名称6.3输出结果的信息,包含用户的信息,有可能除了用户信息还有其他的信息,后面还会加入一些子查询,这个子查询加入进去之后,就有可能没有属性与之对应了。所以将自定义的userCustom作为
-->
<select id="findUserList" parameterType="com.gdc.virtualstall.vo.UserQueryVo" resultType="com.gdc.virtualstall.po.UserCustom">select * from user<!-- where 可以自动的去掉条件中的第一个and--><where><!-- 引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前面加namespace --><include refid="query_user_where"></include><!-- 在这里还要引用其他的sql片段 --></where>
</select>

8.5.4测试代码

/*** 用户信息的综合查询* @throws Exception*/@Testpublic void testFindUserList() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.创建包装对象,设置查询条件UserQueryVo userQueryVo = new UserQueryVo();UserCustom userCustom = new UserCustom();// s4由于使用动态sql,如果不设置某个值,条件不会拼接在sql中 //userCustom.setSex("1");//userCustom.setUsername("张三丰");userQueryVo.setUserCustom(userCustom);// s4.调用IUserMapper的方法List<UserCustom> userCustomList = userMapper.findUserList(null);System.out.println(userCustomList);}

8.6foreach

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

8.6.1 需求

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

(2)sql语句如下:

(3)两种方法:

SELECT * FROM user WHERE id=1 OR id=10 OR id=16;SELECT * FROM user WHERE id IN(1,10,16);

8.6.2 在输入参数类型中添加属性传入多个id

package com.gdc.virtualstall.vo;import java.util.List;import com.gdc.virtualstall.po.UserCustom;/*** 1.用户包装类型* 1.1为什么是叫VO呢?VO表示的是视图层面的对象,而PO指的是持久层的对象,POJO指的是自定义的类似于PO与VO综合体之间的javabean* 1.2在这个类中包装所需要的查询条件* 1.3可以通过组合的方式添加很多的属性。*/
public class UserQueryVo {//s0.foreach属性定义private List<Integer> ids;//s1.用户的查询条件private UserCustom userCustom;public List<Integer> getIds() {return ids;}public void setIds(List<Integer> ids) {this.ids = ids;}public UserCustom getUserCustom() {return userCustom;}public void setUserCustom(UserCustom userCustom) {this.userCustom = userCustom;}//s2.可以包装其它的查询条件,订单、商品
}

8.6.3修改mapper.xml

(1)WHERE id=1 OR id=10 OR id=16

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

<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 test="ids!=null"><!-- 10.3使用foreach遍历传入的ids (1)collection:指定输入对象中集合属性(2)item:每次遍历生成的对象名(3)open:开始遍历时需要拼接的串(4)close:结束遍历时需要拼接的串(5)遍历的两个对象中间需要拼接的串--><!-- 使用实现下边的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></if>
</sql>

8.6.4测试代码

 /*** 用户信息的综合查询* @throws Exception*/@Testpublic void testFindUserList() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.创建包装对象,设置查询条件UserQueryVo userQueryVo = new UserQueryVo();UserCustom userCustom = new UserCustom();// s4由于使用动态sql,如果不设置某个值,条件不会拼接在sql中 //userCustom.setSex("1");//userCustom.setUsername("张三丰");userQueryVo.setUserCustom(userCustom);// s5.传入多个idList<Integer> ids = new ArrayList<Integer>();ids.add(1);ids.add(10);ids.add(16);userQueryVo.setIds(ids);// s4.调用IUserMapper的方法List<UserCustom> userCustomList = userMapper.findUserList(userQueryVo);System.out.println(userCustomList);}

8.6.5另外一个sql片段

<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 test="ids!=null"><!-- 10.3使用foreach遍历传入的ids (1)collection:指定输入对象中集合属性(2)item:每次遍历生成的对象名(3)open:开始遍历时需要拼接的串(4)close:结束遍历时需要拼接的串(5)遍历的两个对象中间需要拼接的串--><!-- 使用实现下边的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> --><!-- 实现 and id IN(1,10,16)拼接--><foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=","><!-- 每次遍历需要拼接的串 -->#{user_id}</foreach></if></if>
</sql>
 * @throws Exception*/
@Test
public void testFindUserList() throws Exception {// s1.通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();// s2.创建IUserMapper对象,mybatis自动生成mapper代理对象IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);// s3.创建包装对象,设置查询条件UserQueryVo userQueryVo = new UserQueryVo();UserCustom userCustom = new UserCustom();// s4由于使用动态sql,如果不设置某个值,条件不会拼接在sql中 //userCustom.setSex("1");//userCustom.setUsername("张三丰");userQueryVo.setUserCustom(userCustom);// s5.传入多个idList<Integer> ids = new ArrayList<Integer>();ids.add(1);ids.add(10);ids.add(16);userQueryVo.setIds(ids);// s4.调用IUserMapper的方法List<UserCustom> userCustomList = userMapper.findUserList(userQueryVo);System.out.println(userCustomList);
}

#### 8.6.5另外一个sql片段
```xml
<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 test="ids!=null"><!-- 10.3使用foreach遍历传入的ids (1)collection:指定输入对象中集合属性(2)item:每次遍历生成的对象名(3)open:开始遍历时需要拼接的串(4)close:结束遍历时需要拼接的串(5)遍历的两个对象中间需要拼接的串--><!-- 使用实现下边的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> --><!-- 实现 and id IN(1,10,16)拼接--><foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=","><!-- 每次遍历需要拼接的串 -->#{user_id}</foreach></if></if>
</sql>

9.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

9.1微信打赏

9.2支付宝打赏

【01】MyBatis基础知识相关推荐

  1. 【计算机基础】01计算机基础知识

    第1章 计算机基础知识 1.1 概述 1.1.1 计算机的发展史    1942年2月,美国宾夕法尼亚大学研制出世界上第一台电子多用途数字计算机ENIAC. 5个发展时代: 1. 第一代计算机 第一代 ...

  2. 01.软件测试基础知识整合

    软件测试基础 前言 一.什么是软件测试 二.软件测试的目的 三.软件测试的基本流程 四.测试分类 五.测试用例 1.什么是测试用例 2.测试用例的重要性 3.测试用例的设计方法 4.测试点分析 5.如 ...

  3. 【笔记】网易微专业-Web安全工程师-01.WEB基础知识

    课程概述: 本课是基础中的基础,通俗易懂的讲解了Web的本质和Web开发的基础知识.对于Web小白,建议从头开始抓紧学习:对于已经有一定Web基础知识的同学,建议快速的过一遍,夯实基础. 课程大纲: ...

  4. 电子计算机的基本结构基于存储程序,01计算机基础知识题(50道)

    有答案的 计算机基础知识测试题(带答案) 第一章 计算机基础知识习题 三.填空题 1.到目前为止,电子计算机的基本结构基于存储程序思想,这个思想最早是由提出的. 2.微型机硬件的最小配置包括主机.键盘 ...

  5. 密码算法学习笔记01:基础知识-公钥密码和混合密码系统

    来自书籍<图解密码技术 第三版.pdf> 密码算法基础知识-公钥密码和混合密码系统 一.公钥密码 公钥密码--用公钥加密,用私钥解密. 公钥密码无需向接收者配送用于解密的钥匙,只需向发送者 ...

  6. MyBatis基础知识汇总

    文章目录 MyBatis简介 简介 MyBatis历史 为什么要用MyBatis? MyBatis入门 安装 从XML中构建SqlSessionFactory 不使用 XML 构建 SqlSessio ...

  7. MyBatis从入门到精通(一)—MyBatis基础知识和快速入门

    Mybatis简介 原始jdbc操作(查询数据) Connection connection = null;PreparedStatement preparedStatement = null;Res ...

  8. 微信公众号(01)---相关基础知识

    本文主要普及一下微信公众号相关基本知识以及开发者模式的开启. 一.微信公众号分类 微信公众号主要分为三类.订阅号.服务号.企业号. 首先看看官方对于它们的说明 (1) 订阅号: 为媒体和个人提供一种新 ...

  9. Shell脚本编程01:基础知识

    Shell脚本与Windows/Dos下的批处理相似,就是将各类命令预先放入到一个文件中,然后执行该文件,便可以达到与批处理类似的功能,主要是方便管理员进行设置或者管理用的. 换句话来说,shell脚 ...

  10. SpringMVC+Mybatis基础知识和配置

    SpringMVC和Mybatis简单的记录一下,因为现在有比较新的SpringBoot和Mybatis plus简化了很多步骤. SpringMVC 使用 创建maven项目,pom.xml < ...

最新文章

  1. python工具是什么-python有什么好用的持续集成工具么?
  2. 【tool】测试用例检查表范例
  3. Taran 缩点【bzoj1529】[POI2005]ska Piggy banks
  4. Memcache-No.03 Memcache相关安装、部署、启动、监控
  5. SAP CRM WebClient UI端到端的字段扩展
  6. 区块链上智能合约的讲解
  7. C语言课后习题(51)
  8. 抖音举办平台治理开放日 半年捣毁25个黑产团伙
  9. java方法:flush()
  10. 2021年最后一个月
  11. Objective-C中的位运算符用法
  12. 流浪猫的故事看质量人员需求
  13. G-sensor概述及常用芯片整理
  14. 2022数字化智慧工地助力建筑施工企业数字化转型
  15. 后端接口生成微信小程序二维码Api
  16. PDF文件修改最常用的方式有哪些?
  17. 5G时代下,如何做好个人信息保护?
  18. 不一样的课程表,不一样的Excle--用Excle进行设计(12):网状结构
  19. 用 Androidx + 蓝牙HC05 点灯(2): Handler 掌舵人 和 Thread 线人,逮着蓝牙老大说黑话:此灯为我开,101011...
  20. 网页突然乱码_网页中乱码怎么办?

热门文章

  1. centos7安装搜狗拼音
  2. 《别做正常的傻瓜》1——结果偏见
  3. 杀毒软件简介:杀毒软件原理,教你如何选择一个好的杀毒软件
  4. 宁宛 机器人_忠犬机器人3
  5. 小白网安学习日记(2) hacknet游戏(模拟黑客入侵的游戏)
  6. ModSecurity规则
  7. 对抗样本生成算法之DeepFool算法
  8. QQ微信实现连续发送消息【代码实现】
  9. Error installing to Instantiated: name=AttachmentStore state=Described
  10. sre工程师_什么是SRE? 现场可靠性工程师的重要作用