Mybatis的复习(一)

Mybatis的复习

  • 创建一个maven项目
  • 开发环境
    • maven依赖环境
  • 创建mysql数据库
  • 创建表
  • 插入数据
  • jdbc程序问题总结
    • 使用jdbc查询mysql数据库中用户表的记录
    • 测试程序
    • 问题总结
  • mybatis是什么
  • mybatis框架
  • mybatis环境搭建
    • 项目结构图
  • 日志的输出
  • 根据用户id(主键)查询用户信息
    • 创建po类
    • 映射文件
    • 在SqlMapConfig.xml加载映射文件
    • 程序编写
  • 根据用户名称模糊查询用户信息
    • 修改映射文件User.xml
    • 修改测试程序
    • 使用concat函数根据用户名称模糊查询用户信息
  • #{}和${}总结
  • selectOne和selectList的区别
  • 添加用户
    • 修改User.xml
    • 测试程序
    • 控制台输出
    • 新增用户返回新增用户的主键
      • mysql数据库中 自增主键返回
  • 删除用户
  • 更新用户
  • mybatis与hibernate的区别与应用
  • mybatis开发 Dao的方法
    • SqlSession使用范围
      • SqlSessionFactoryBuilder
      • SqlSessionFactory
      • SqlSession
    • 原始dao开发方法(程序员需要写dao接口和dao实现类)
      • dao接口
      • dao接口实现类
      • dao接口实现类测试
      • 原始Dao开发问题
  • Mapper动态代理方式
  • SqlMapConfig.xml
    • properties属性
  • settings全局参数配置
    • mybatis的settings全局参数配置
  • typeAliases(别名)
    • mybatis官网对typeAliases别名的介绍
    • 批量定义别名
  • typeHandlers(类型处理器)
    • mybatis官网typeHandlers的介绍
  • mappers(映射配置)
    • 通过resource加载单个映射文件
    • 通过mapper接口加载单个mapper
    • 批量加载mapper(推荐使用)
  • 输入映射
    • 需求
    • 定义包装类型pojo
  • 输出映射
    • resultType
    • 总结
  • resultMap
    • resultMap使用方法
      • 定义resultMap
  • 动态Sql
    • 需求
  • Sql片段
    • 定义sql片段
    • 使用sql片段
  • foreach
    • 需求
    • 在输入参数类型中添加List ids传入多个id
        • 另外一个sql的实现

创建一个maven项目

Mybatis的复习(一)_第1张图片

开发环境

java环境:jdk1.8
eclipse:
mysql

maven依赖环境

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<groupId>cn.companygroupId>
	<artifactId>mybatisartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<packaging>warpackaging>
	<dependencies>
		
		<dependency>
			<groupId>org.mybatisgroupId>
			<artifactId>mybatisartifactId>
			<version>3.5.4version>
		dependency>
		
		<dependency>
			<groupId>log4jgroupId>
			<artifactId>log4jartifactId>
			<version>1.2.17version>
		dependency>
		
		<dependency>
			<groupId>mysqlgroupId>
			<artifactId>mysql-connector-javaartifactId>
			<version>8.0.19version>
		dependency>
		
		<dependency>
			<groupId>junitgroupId>
			<artifactId>junitartifactId>
			<version>4.12version>
			<scope>testscope>
		dependency>
	dependencies>
project>

创建mysql数据库

//创建数据库
create database mybatis;

创建表

//创建用户表
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;
//创建订单表
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;
//创建商品表

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;
//创建订单详细表
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;

插入数据

INSERT INTO `user` ( `id`, `username`, `birthday`, `sex`, `address` )
VALUES
	( 1, '王五', NULL, '2', NULL ),
	( 10, '张三', '2014-07-10', '1', '北京市' ),
	( 16, '张小明', NULL, '1', '河南郑州' ),
	( 22, '陈小明', NULL, '1', '河南郑州' ),
	( 24, '张三丰', NULL, '1', '河南郑州' ),
	( 25, '陈小明', NULL, '1', '河南郑州' ),
	( 26, '王五', NULL, NULL, NULL );
INSERT INTO `items` ( `id`, `name`, `price`, `detail`, `pic`, `createtime` )
VALUES
	( 1, '台式机', 3000.0, '该电脑质量非常好!!!!', NULL, '2015-02-03 13:22:53' ),
	( 2, '笔记本', 6000.0, '笔记本性能好,质量好!!!!!', NULL, '2015-02-09 13:22:57' ),
	( 3, '背包', 200.0, '名牌背包,容量大质量好!!!!', NULL, '2015-02-06 13:23:02' );
INSERT INTO `orders` ( `id`, `user_id`, `number`, `createtime`, `note` )
VALUES
	( 3, 1, '1000010', '2015-02-04 13:22:35', NULL ),
	( 4, 1, '1000011', '2015-02-03 13:22:41', NULL ),
	( 5, 10, '1000012', '2015-02-12 16:13:23', NULL );
INSERT INTO `orderdetail` ( `id`, `orders_id`, `items_id`, `items_num` )
VALUES
	( 1, 3, 1, 1 ),
	( 2, 3, 2, 3 ),
	( 3, 4, 3, 4 ),
	( 4, 4, 2, 3 );

jdbc程序问题总结

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

pom依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0modelVersion>
  <groupId>cn.companygroupId>
  <artifactId>mybatisartifactId>
  <version>0.0.1-SNAPSHOTversion>
  <packaging>warpackaging>
  <dependencies>
  
  	<dependency>
  		<groupId>mysqlgroupId>
  		<artifactId>mysql-connector-javaartifactId>
  		<version>8.0.18version>
  	dependency>
  dependencies>
project>

测试程序

package test;

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

/**
 * @author 86182
 * @date
 * @description: 通过单独的jdbc程序,总结其中的问题
 */
public class TestCase {
	public static void main(String[] args) {
		// 数据库连接
		Connection connection = null;
		// 预编译的Statement,使用预编译的Statement提高数据库性能
		PreparedStatement preparedStatement = null;
		// 结果 集
		ResultSet resultset = null;
		try {
			// 加载数据库驱动
			Class.forName("com.mysql.cj.jdbc.Driver");
			// 通过驱动管理类获取数据库链接
			connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&serverTimezone=Asia/Shanghai",
					"root", "root");
			// 定义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) {
					e.printStackTrace();
				}
			}
			if(preparedStatement!=null){
				try {
					preparedStatement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

测试结果
Mybatis的复习(一)_第2张图片

问题总结

1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响 数据库性能。
设想:使用数据库连接池管理数据库连接
2、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护
将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。
3、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护
将sql语句及占位符号和参数全部配置在xml中
4、从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护
将查询的结果集,自动映射成java对象

mybatis是什么

mybatis是一个持久层的框架,是apache下的顶级项目。
mybatis托管到goole code下,再后来托管到github
mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,
自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
可以将向 preparedStatement中的输入参数自动进行输入映射
将查询结果集灵活映射成java对象。(输出映射)

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的复习(一)_第3张图片

mybatis环境搭建

mybatis运行环境(jar包):
从https://github.com/mybatis/mybatis-3/releases下载,3.5.4版本
mybatis的jar下载地址
lib下:依赖包
mybatis-3.5.4.jar:核心 包
mybatis-3.5.4.pdf,操作指南
加入mysql的驱动包
mysql的驱动包下载地址
日志的jar包下载地址
log4j的jar下载地址

项目结构图

Mybatis的复习(一)_第4张图片

日志的输出

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

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

创建po类

Po类作为mybatis进行sql映射使用,po类通常与数据库表对应

package cn.itcast.mybatis.po;

import java.util.Date;

public class User {
	//属性名和数据库表的字段对应
	private int id;
	private String username;// 用户姓名
	private Date birthday;// 生日
	private String sex;// 性别
	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 Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
				+ address + "]";
	}
}

映射文件

映射文件命名:
User.xml(原始ibatis命名),mapper代理开发映射文件名称叫XXXMapper.xml,
比如:UserMapper.xml、 ItemsMapper.xml
在映射文件中配置sql语句。




<mapper namespace="cn.itcast.mybatis.po">
	<select id="findAll" resultType="cn.itcast.mybatis.po.User">
		select * from user
	select>
	
	
	
	<select id="findUserById" resultType="cn.itcast.mybatis.po.User" parameterType="int">
		select * from user where id=#{id}
	select>
mapper>

在SqlMapConfig.xml加载映射文件



<configuration>
	
	<properties resource="db.properties"/>
	<typeAliases>
		<package name="cn.itcast.mybatis.po"/>
	typeAliases>
	
	<environments default="development">
		<environment id="development">
			
			<transactionManager type="JDBC"/>
			
			<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>
	<mappers>
		<mapper resource="sqlmap/User.xml"/>
	mappers>
configuration>

程序编写

package cn.itcast.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 org.junit.Test;

import cn.itcast.mybatis.po.User;
/**
 * 
 *@author 86182
 *@date 2020年2月27日上午12:11:32
 *@description:入门程序
 */
public class MybatisFirst {
		//根据id查询用户信息,得到一条记录结果
		@Test
		public void findUserByIdTes() throws IOException {
			//mybatis的配置文件
			String resource="SqlMapConfig.xml";
			//得到配置文件流
			InputStream inputStream=Resources.getResourceAsStream(resource);
			//创建会话工厂,传入mybatis的配置文件信息
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			//通过工厂得到SqlSession
			SqlSession ss=sf.openSession();
			//通过SqlSession操作数据库
			// 第一个参数:映射文件中statement的id,等于=namespace+"."+statement的id
			// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数
			// sqlSession.selectOne结果 是与映射文件中所匹配的resultType类型的对象
			// selectOne查询出一条记录
			User user=ss.selectOne("findUserById",1);
			System.out.println(user.getUsername());
			ss.commit();
			//释放资源
			ss.close();
		}
		
}

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

修改映射文件User.xml




<mapper namespace="cn.itcast.mybatis.po">
	<select id="findAll" resultType="cn.itcast.mybatis.po.User">
		select * from user
	select>
	
	
	
	<select id="findUserById" resultType="cn.itcast.mybatis.po.User" parameterType="int">
		select * from user where id=#{id}
	select>
	
	<select id="findUserByName" resultType="cn.itcast.mybatis.po.User" parameterType="java.lang.String">
		select * from user where username like '%${username}%'
	select>
mapper>

修改测试程序

Mybatis的复习(一)_第5张图片

使用concat函数根据用户名称模糊查询用户信息

修改映射文件User.xml



<mapper namespace="cn.itcast.mybatis.po">
	<select id="findUserByName2" resultType="cn.itcast.mybatis.po.User" parameterType="java.lang.String">
		select * from user where username like concat('%',#{username},'%')
	select>
mapper>

测试程序

@Test
		public void findUserByName2Test() throws IOException{
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			List<User> user=ss.selectList("findUserByName2", "王五");
			for (User u : user) {
				System.out.println(u.getId()+"——————"+u.getSex());
			}
			ss.commit();
			ss.close();
		}

控制台输出结果
Mybatis的复习(一)_第6张图片

#{}和${}总结

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类
型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简>单类型值,#{}括号中可以是value或其它名称。
表 示 拼 接 s q l 串 , 通 过 {}表示拼接sql串,通过 sql{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}可以接 收简单类型值或pojo属性值,如果parameterType传输单个简单类型值, pojoparameterType{}括号中只能是value。
会引起sql注入,所以不建议使用

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可以查询一条或多条记录。

添加用户

修改User.xml

在User.xml中添加如下代码


	<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		insert into user (id,username,birthday,sex,address) values(null,#{username},#{birthday},#{sex},#{address})
	insert>

测试程序

@Test
		public void insertUser() throws IOException {
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			User user=new User();
			user.setUsername("Alice");
			user.setSex("1");
			user.setBirthday(new Date());
			user.setAddress("北京房山区");
			ss.insert("insertUser", user);
			ss.commit();
			ss.close();
		}

控制台输出

Mybatis的复习(一)_第7张图片

新增用户返回新增用户的主键

mysql数据库中 自增主键返回

  1. 第一种方式

修改User.xml
在Insert插入语句中增加useGeneratedKeys=true,
keyProperty=“id”

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" useGeneratedKeys="true" keyProperty="id">
		insert into user (id,username,birthday,sex,address) values(null,#{username},#{birthday},#{sex},#{address})
	insert>

测试程序

@Test
		public void insertUser() throws IOException {
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			User user=new User();
			user.setUsername("Halen");
			user.setSex("1");
			user.setBirthday(new Date());
			user.setAddress("北京房山区");
			ss.insert("insertUser", user);
			//获取新增数据的key(主键)
			System.out.println(user.getId());
			System.out.println(user);
			ss.commit();
			ss.close();
		}

控制台输出
Mybatis的复习(一)_第8张图片
2. 第二种方式

mysql自增主键,执行insert提交之前自动生成一个自增主键
通过mysql函数获取到刚插入记录的自增主键
LAST_INSERT_ID()
是在insert之后调用LAST_INSERT_ID()函数查询自增主键

通过修改sql映射文件,可以将mysql自增主键返回:


	<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" >
		
		<selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">
			SELECT LAST_INSERT_ID()
		selectKey>
		insert into user (id,username,birthday,sex,address) values(null,#{username},#{birthday},#{sex},#{address})
	insert>

删除用户

User.xml中添加如下代码


<delete id="deleteUser" parameterType="int">
		delete from user where id=#{id}
	delete>

测试程序

@Test
		public void deleteUserTest() throws IOException {
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			ss.delete("deleteUser", 29);
			ss.commit();
			ss.close();
		}

执行结果如下
Mybatis的复习(一)_第9张图片

更新用户

User.xml中添加如下代码


	<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
		update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
	update>

测试程序

@Test
		public void updateUserTest() throws IOException {
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			User user=new User();
			user.setId(31);
			user.setBirthday(new Date());
			user.setAddress("湖北武汉");
			user.setSex("0");
			user.setUsername("张俊");
			ss.update("updateUser", user);
			ss.commit();
			ss.close();
		}

测试程序也可以如下写

@Test
		public void updateUser2Test() throws IOException {
			String resource="SqlMapConfig.xml";
			InputStream inputStream=Resources.getResourceAsStream(resource);
			SqlSessionFactory sf=new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession ss=sf.openSession();
			User user=ss.selectOne("findUserById",31);
			user.setBirthday(new Date());
			user.setAddress("湖北武汉");
			user.setSex("0");
			user.setUsername("李四");
			ss.update("updateUser", user);
			ss.commit();
			ss.close();
		}

测试结果
Mybatis的复习(一)_第10张图片

mybatis与hibernate的区别与应用

hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的
应用场景:
用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM
框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)
应用场景:
适用与需求变化较多的项目,比如:互联网项目
企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。

mybatis开发 Dao的方法

SqlSession使用范围

SqlSessionFactoryBuilder

通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
SqlSessionFactoryBuilder当成一个工具类使用即可
不需要使用单例模式管理SqlSessionFactoryBuilder
在需要创建SqlSessionFactoryBuilder时候,只需要new一次SqlSessionFactoryBuilder

SqlSessionFactory

通过SqlSessionFactory创建SqlSession,使用单例模式管理SqlSessionFactory
(工厂一旦创建,使用一个实例)
将mybatis和spring整合后,使用单例模式管理SqlSessionFactory

SqlSession

SqlSession是一个面向用户(程序员)的接口
SqlSession提供了很多操作数据库的方法:如selectOne(返回单个对象)、selectList(返回单个或多个对象)、
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性

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

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

程序员需要写dao接口和dao实现类
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

dao接口

package cn.itcast.mybatis.dao;

import cn.itcast.mybatis.po.User;

/**
 * 
 * @author 86182
 * @version 1.0
 */
public interface UserDao {
	// 根据id查询用户信息
	public User findUserById(int id) throws Exception;

	// 添加用户信息
	public void insertUser(User user) throws Exception;

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

dao接口实现类

package cn.itcast.mybatis.dao;

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

import cn.itcast.mybatis.po.User;

public class UserDaoImpl implements UserDao {
	//需要向dao实现类中注入SqlSessionFactory
	//通过构造方法注入
	private SqlSessionFactory sqlSessionFactory;
	public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory=sqlSessionFactory;
	}
	public User findUserById(int id) throws Exception {
		SqlSession sqlSession=sqlSessionFactory.openSession();
		User user= sqlSession.selectOne("findUserById",id);
		sqlSession.commit();
		//释放资源
		sqlSession.close();
		return user;
	}

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

	}

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

}

dao接口实现类测试

package cn.itcast.mybatis.dao;

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 cn.itcast.mybatis.po.User;

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

	@Test
	public void testFindUserById() throws Exception {
//		fail("Not yet implemented");
		//创建UserDao
		UserDao userDao=new UserDaoImpl(sqlSessionFactory);
		//调用UserDao
		User user=userDao.findUserById(1);
		System.out.println(user);
	}

}

程序输入结果
Mybatis的复习(一)_第11张图片

原始Dao开发问题

1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
2、 调用sqlsession方法时将statement的id硬编码了
3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。

Mapper动态代理方式

程序员还需要编写mapper.xml映射文件
程序员编写mapper接口需要遵循一些开发规范,mybatis可以自己生成mapper接口实现类代理对象

开发规范:

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



<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
mapper>
  1. mapper.java接口中的方法名和mapper.xml中statement的id一致
  2. mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
  3. mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
    Mybatis的复习(一)_第12张图片
    Mybatis的复习(一)_第13张图片
    修改UserMapper.xml



<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
	<select id="findUserById" resultType="User" parameterType="int">
		select * from user where id=#{id}
	select>
	<select id="findUserByName" resultType="User" parameterType="java.lang.String">
		select * from user where username like concat('%',#{username},'%')
	select>
	<select id="findAllUsers" resultType="User">
		select * from user
	select>
	<insert id="insertUser" parameterType="User">
		insert into user values (null,#{username},#{birthday},#{sex},#{address})
	insert>
	<update id="updateUser" parameterType="User">
		update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
	update>
	<delete id="deleteUser" parameterType="int">
		delete from user where id=#{id}
	delete>
mapper>

在SqlMapConfig.xml中引用UserMapper.xml
Mybatis的复习(一)_第14张图片
修改UserMapper
Mybatis的复习(一)_第15张图片
测试程序

package cn.itcast.mybatis.mapper;

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

import cn.itcast.mybatis.po.User;

public class UserMapperTest {
	SqlSessionFactory sf;
	SqlSession ss;

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

	@After
	public void after() {
		ss.commit();
		ss.close();
	}

	/**
	 * 
	 * 查询所有的用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindAllUsers() throws Exception {
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findAllUsers();
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 
	 * 根据id查询用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserById() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		User user = mapper.findUserById(27);
		System.out.println(user);
	}

	/**
	 * 根据用户名查询用户列表
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserByName() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findUserByName("明");
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 添加用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testInsertUser() throws Exception {
		User user = new User();
		user.setBirthday(new Date());
		user.setAddress("安徽黄山");
		user.setSex("1");
		user.setUsername("张筱雨");
		UserMapper mapper = ss.getMapper(UserMapper.class);
		mapper.insertUser(user);
	}

	/**
	 * 更新用户信息
	 * @throws Exception
	 */
	@Test
	public void testUpdateUser() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> user = mapper.findUserByName("张筱雨");
		for (User user2 : user) {
			user2.setUsername("张晓雨");
			mapper.updateUser(user2);
		}
	}
	/**
	 * 删除用户信息
	 * @throws Exception
	 */
	@Test
	public void testDeleteUser()  throws Exception{
		UserMapper mapper=ss.getMapper(UserMapper.class);
		mapper.deleteUser(32);
	}
}

总结:

  • 如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
  • 如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。
  • 系统 框架中,dao层的代码是被业务层公用的
  • mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求

SqlMapConfig.xml

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

properties属性

将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值
将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties。
db.properties文件配置如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

在SqlMapConfig.xml加载属性文件
Mybatis的复习(一)_第16张图片
MyBatis 将按照下面的顺序来加载属性:

  • 在 properties 元素体内定义的属性首先被读取
  • 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
  • 最后读取parameterType传递的属性,它会覆盖已读取的同名属性
  • 不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中
  • 在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX
  • 通过parameterType传递的属性具有最高优先级,resource或 url 加载的属性次之,
  • 最低优先级的是 properties 元素体内定义的属性

settings全局参数配置

mybatis框架在运行时可以调整一些运行参数
例如:开启二级缓存、开启延迟加载
全局参数将会影响mybatis的运行行为

mybatis的settings全局参数配置

typeAliases(别名)

在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些
别名,在mapper.xml中通过别名定义,方便开发。

mybatis官网对typeAliases别名的介绍

自定义别名:
Mybatis的复习(一)_第17张图片
引用别名:
在这里插入图片描述

批量定义别名

在这里插入图片描述

typeHandlers(类型处理器)

mybatis中通过typeHandlers完成jdbc类型和java类型的转换。
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.

mybatis官网typeHandlers的介绍

mappers(映射配置)

通过resource加载单个映射文件

使用相对于类路径的资源

在这里插入图片描述

通过mapper接口加载单个mapper

使用mapper接口类路径

Mybatis的复习(一)_第18张图片
按照上边的规范,将mapper.java和mapper.xml放在一个目录 ,且同名。
Mybatis的复习(一)_第19张图片

批量加载mapper(推荐使用)

Mybatis的复习(一)_第20张图片

输入映射

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

需求

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

定义包装类型pojo

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

用户的扩展类

package cn.itcast.mybatis.po;
/**
 *
 * @author 86182
 * @description:
 * 用户的扩展类
 *
 */
public class UserCustom extends User{
	//可以扩展用户的信息
}

包装类

package cn.itcast.mybatis.po;
/**
 * 
 * @author 86182
 *@Description:
 *
 *包装类型
 */
public class UserQueryVo {
	//在这里包装所需要的查询条件
	//用户查询条件
	private UserCustom userCustom ;

	public UserCustom getUserCustom() {
		return userCustom;
	}

	public void setUserCustom(UserCustom userCustom) {
		this.userCustom = userCustom;
	}
	
	//可以包装其他的查询条件、订单、商品
	
}

修改UserMapper.xml,添加如下代码


	<select id="findUserList" parameterType="UserQueryVo" resultType="UserCustom">
		select * from user where user.sex=#{userCustom.sex} and user.username like CONCAT('%',#{userCustom.username},'%')
	select>

Mybatis的复习(一)_第21张图片
修改UserMapper.java
Mybatis的复习(一)_第22张图片
测试程序

package cn.itcast.mybatis.mapper;

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

import cn.itcast.mybatis.po.User;
import cn.itcast.mybatis.po.UserCustom;
import cn.itcast.mybatis.po.UserQueryVo;

public class UserMapperTest {
	SqlSessionFactory sf;
	SqlSession ss;

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

	@After
	public void after() {
		ss.commit();
		ss.close();
	}

	/**
	 * 
	 * 查询所有的用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindAllUsers() throws Exception {
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findAllUsers();
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 
	 * 根据id查询用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserById() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		User user = mapper.findUserById(27);
		System.out.println(user);
	}

	/**
	 * 根据用户名查询用户列表
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserByName() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findUserByName("明");
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 添加用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testInsertUser() throws Exception {
		User user = new User();
		user.setBirthday(new Date());
		user.setAddress("安徽黄山");
		user.setSex("1");
		user.setUsername("张筱雨");
		UserMapper mapper = ss.getMapper(UserMapper.class);
		mapper.insertUser(user);
	}

	/**
	 * 更新用户信息
	 * @throws Exception
	 */
	@Test
	public void testUpdateUser() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> user = mapper.findUserByName("张筱雨");
		for (User user2 : user) {
			user2.setUsername("张晓雨");
			mapper.updateUser(user2);
		}
	}
	/**
	 * 删除用户信息
	 * @throws Exception
	 */
	@Test
	public void testDeleteUser()  throws Exception{
		UserMapper mapper=ss.getMapper(UserMapper.class);
		mapper.deleteUser(32);
	}
	/**
	 * 用户信息的综合查询
	 * @throws Exception
	 */
	@Test
	public void testFindUserList() throws Exception {
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper mapper = ss.getMapper(UserMapper.class);
		//创建包装对象,设置查询条件
		UserQueryVo userQueryVo=new UserQueryVo();
		UserCustom userCustom=new UserCustom();
		userCustom.setSex("1");
		userCustom.setUsername("张");
		userQueryVo.setUserCustom(userCustom);
		//调用mapper的方法
		List<UserCustom> users = mapper.findUserList(userQueryVo);
		for (UserCustom user : users) {
			System.out.println(user);
		}
	}
}

Mybatis的复习(一)_第23张图片

输出映射

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

resultType

需求:
用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。
修改UserMapper.xml


<select id="findUserListCount" resultType="int" parameterType="UserQueryVo">
		select count(*) from user where username=#{userCustom.username} and password=#{userCustom.password}
	select>

UserMapper.java中添加如下代码

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

测试程序

package cn.mybatis.mapper;

import java.io.IOException;
import java.io.InputStream;
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.After;
import org.junit.Before;
import org.junit.Test;

import cn.mybatis.pojo.User;
import cn.mybatis.pojo.UserCustom;
import cn.mybatis.pojo.UserQueryVo;

public class UserMapperTest {
	SqlSessionFactory sf;
	SqlSession ss;

	@Before
	public void before() throws IOException {
		String resource = "SqlMapConfig.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		sf = new SqlSessionFactoryBuilder().build(inputStream);
		ss = sf.openSession();
	}

	@After
	public void after() {
		ss.commit();
		ss.close();
	}

	/**
	 * 增加用户
	 * 
	 * @throws Exception
	 */
	@Test
	public void testInsertUser() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		User user = new User();
		user.setUsername("张翰");
		user.setPassword("1234");
		mapper.insertUser(user);
		System.out.println(user.getId());
	}

	/**
	 * 删除用户
	 * 
	 * @throws Exception
	 */
	@Test
	public void testDeleteUser() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		mapper.deleteUser(3);
	}

	/**
	 * 修改用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testUpdateUser() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		User user = mapper.findUserById(1);
		user.setUsername("张良");
		int count = mapper.updateUser(user);
		System.out.println(count);
	}

	/**
	 * 查找所有的用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindAllUsers() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findAllUsers();
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 根据id寻找用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserById() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		User user = mapper.findUserById(1);
		System.out.println(user);
	}

	/**
	 * 根据用户名模糊查询,查找相关用户信息
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserByUserName() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		List<User> users = mapper.findUserByUserName("良");
		for (User user : users) {
			System.out.println(user);
		}
	}

	/**
	 * 用户信息综合查询
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserList() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		UserCustom userCustom = new UserCustom();
		userCustom.setPassword("123456");
		userCustom.setUsername("张良");
		UserQueryVo userQueryVo = new UserQueryVo();
		userQueryVo.setUserCustom(userCustom);
		List<UserCustom> userCustoms = mapper.findUserList(userQueryVo);
		for (UserCustom userCustom2 : userCustoms) {
			System.out.println(userCustom2.getId() + "-" + userCustom.getUsername() + "-" + userCustom.getPassword());
		}
	}
	/**
	 * 用户信息综合查询
	 * 
	 * @throws Exception
	 */
	@Test
	public void testFindUserListCount() throws Exception {
		UserMapper mapper = ss.getMapper(UserMapper.class);
		UserCustom userCustom = new UserCustom();
		userCustom.setPassword("123456");
		userCustom.setUsername("张良");
		UserQueryVo userQueryVo = new UserQueryVo();
		userQueryVo.setUserCustom(userCustom);
		int count = mapper.findUserListCount(userQueryVo);
		System.out.println(count);
	}
}

Mybatis的复习(一)_第24张图片

总结

1.查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射
2.不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。在mapper.java指定的方法返回值类型不一样:

  • 输出单个pojo对象,方法返回值是单个对象类型
// 根据id查找用户信息
	public User findUserById(int id) throws Exception;
  • 输出pojo对象list,方法返回值是List
// 根据用户名称查找用户信息
	public List<User> findUserByUserName(String username) throws Exception;

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

resultMap

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

resultMap使用方法

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
1.定义resultMap
2.使用resultMap作为statement的输出映射类型

定义resultMap

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


	
	<resultMap type="User" id="userResultMap">
		
		<id column="id_" property="id"/>
		
		<result column="username_" property="username"/>
		<result column="password_" property="password"/>
	resultMap>
	
	<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
		select id id_,username username_,password password_ from user
	select>

在UserMapper.java中添加如下代码:
在这里插入图片描述
测试程序

Mybatis的复习(一)_第25张图片

总结:
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

动态Sql

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

需求

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

UserMapper.xml中


<select id="findUserListBySql" resultType="UserCustom"
		parameterType="UserQueryVo">
		select * from user
		<where>
			<if test="userCustom!=null">
				<if test="userCustom.username!=null and userCustom.username!=''">
					and username like concat('%',#{userCustom.username},'%')
				if>
				<if test="userCustom.password!=null and userCustom.password!=''">
					and password=#{userCustom.password}
				if>
			if>
		where>
	select>

UserMapper.java中添加如下代码:

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

测试程序与结果:
Mybatis的复习(一)_第26张图片

Sql片段

定义sql片段

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

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


	<sql id="query_useer_where">
		<if test="userCustom!=null">
			<if test="userCustom.username!=null and userCustom.username!=''">
				and username like concat('%',#{userCustom.username},'%')
			if>
			<if test="userCustom.password!=null and userCustom.password!=''">
				and password=#{userCustom.password}
			if>
		if>
	sql>

使用sql片段

在UserMapper.xml中继续添加如下代码:

	
	<select id="findUserListBySql" resultType="UserCustom"
		parameterType="UserQueryVo">
		select * from user
		
		<where>

			
			<include refid="query_useer_where">include>
			
		where>
	select>

修改UserMapper.java,添加如下代码

// 使用sql片段进行用户信息综合查询
	public List<UserCustom> findUserListBySql(UserQueryVo userQueryVo) throws Exception;

测试程序与结果
Mybatis的复习(一)_第27张图片

foreach

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

需求

在用户查询列表和查询总数的statement中增加多个id输入查询
sql语句如下:
两种方法:
select * from user where id=1 or id=2;
select * from user where id in(1,2);

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

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


	<select id="findUserListBySql" resultType="UserCustom"
		parameterType="UserQueryVo">
		select * from user
		
		<where>

			
			<include refid="query_useer_where">include>
			
		where>
	select>
	
	<sql id="query_useer_where">
		<if test="userCustom!=null">
			<if test="userCustom.username!=null and userCustom.username!=''">
				and username like concat('%',#{userCustom.username},'%')
			if>
			<if test="userCustom.password!=null and userCustom.password!=''">
				and password=#{userCustom.password}
			if>
			<if test="ids!=null">
				
				
				<foreach collection="ids" item="user_id" open="AND (" close=")" separator="OR">
					
					id=#{user_id}
				foreach>
			if>
		if>
	sql>

修改UserQueryVo.java
Mybatis的复习(一)_第28张图片
测试程序与输出结果
Mybatis的复习(一)_第29张图片

另外一个sql的实现

<foreach collection="ids" item="user_id" open="AND id in(" close=")" separator=",">
	#{user_id}
foreach>

你可能感兴趣的:(java,mybatis,java)