mybatis框架(共四天):大纲
1 第一天:mybatis入门
mybatis的概述
mybatis的环境搭建
mybatis入门案例
自定义mybatis框架(主要是为了了解mybatis中执行细节)
2 第二天:mybatis基本使用
mybatis的单标CRUD操作
mybatis的参数和返回值
mybatis的dao编写
mybatis配置的细节
几个标签的使用
3 第三天:mybatis的深入和多表
mybatis的连接池
mybatis的事务控制及设计的方法
mybatis的多表查询
一对多(多对一)
多对多
4 第四天:mybatis的缓存和注解开发
mybatis中的加载时机(查询的时机)
mybatis中的一级缓存,二级缓存
mybatis的注解开发
单表CRUD
多表查询
mybatis框架:第一天
1、框架概述
1.1 什么是框架?
* 通俗一点说,它是我们软件开发中的一套解决方法,不同的框架解决的是不同的问题。
* 使用框架的好处:
框架封装了很多的细节,使开发者可以使用极简的方式实现功能,大大提高开发效率。
* 不同的框架解决不同的问题。------> 提一下三层架构。
mybatis框架:持久层框架,是和数据库交互的
SpringMVC框架:表现层框架。

2.三层架构
表现层:
是用来展示数据的。
业务层:
是处理也无需求的。
持久层:
是和数据库交互的。
3.持久层技术解决方案
JDBC:涉及到三个对象
Connection
PreparedStatement
ResultSet
Spring的JdbcTemplate:
Spring中对jdbc的简单封装
Apache的DBUtils:
它和Spring的JdbcTemplate很像,也是对Jdbc的简单封装
以上这些都不是矿建:
*JDBC是规范
*Spring的JdbcTemplate和Apache的DBUtils都只是工具类。
是对这个规范的一个实现,一个简单的封装,不算是框架。只是一个使用的封装,并没有一
套完整的解决方案,封装的还不够细致。即我们使用中还需要处理很多事情,达不到框架使
开发者用极简的方式实现功能,大大提高开发效率。
4 .mybatis的概述
mybatis是一个持久层框架,用java编写的。
它封装了jdbc操作的很多细节,使开发者只需关注sql语句本身,而无需关注注册驱动,创建
连接等繁杂过程。
它使用了ORM思想实现了结果集的封装。
* ORM:Object Relational Mapping 对象关系映射
简单的说:就是把数据库表和实体类及实体类的属性对应起来
让我们可以操作实体类就可以操作数据库表。
user(表) User(类)
id userId
user_name userName
今天我们需要做到:
实体类中的属性和数据库表中的字段名称保持一致
user(表) User(类)
id id
user_name user_name
表中的列名就是实体类中的字段名称。
1.2、JDBC编程分析
* 1.代码:
```
public static void main(String[] args) {
Connection connection = null;
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 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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
```
2、mybatis的入门
2.1 mybatis的环境搭建
2.1.0 数据库建表
CREATE DATABASE txl_mybatis;
USE txl_mybatis;
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(32) NOT NULL COMMENT '用户名称',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`username`,`birthday`,`sex`,`address`) VALUES (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');

2.1.1 创建maven工程
创建mybatis01的工程,工程信息如下。
Groupid :cn.itcast
ArtifactId : day0602_mybatis01
Packing : jar
2.1.2 添加Mybatis坐标和其他jar包依赖
```
<dependencies>
<!--导入mybatis的坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--因为是数据库的操作还需要:添加mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--日志坐标-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--导入JUNIT依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
```
2.1.3 编写User实体类
package cn.itcast.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
2.1.4 编写持久层接口IUserDao
package cn.itcast.dao;
import cn.itcast.domain.User;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有
* @return
*/
List<User> findAll();
}
2.1.5 编写持久层接口的映射文件IUserDao.xml
*要求:
创建位置:必须和持久层接口在相同的包中。
名称:必须以持久层接口名称命名文件名。扩展名为.xml

*持久层接口的映射文件IUserDao.xml:Mapper的约束
```
<?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">
<!--dao的全限定类名-->
<mapper namespace="cn.itcast.dao.IUserDao">
<!--配置查询所sql-->
<!--操作配置:因为是查询,select标签;id是dao中的方法名-->
<select id="findAll" resultType="cn.itcast.domain.User">
select * from user
</select>
</mapper>
```
2.1.6 编写SqlMapConfig.xml配置文件:Config的约束
* 在resources目录下配置

* 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">
<!--这些都是和数据库相关的,和环境相关的:它是mybatis的主配置文件-->
<configuration>
<!--配置环境:mybatis的主配置文件-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/txl_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="cn/itcast/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
```
2.1.7 mybatis的环境搭建步骤小结
1.创建maven工程,并导入坐标依赖
2.创建实体类和dao接口
3.创建Mybatis的主配置文件
SqlMapConfig.xml
4.创建映射配置文件
IUserDao.xml
* 环境搭建做完了。
2.1.8 mybatis的环境搭建的注意事项
1.创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。在
Mybatis中它把持久层的操作接口名称和映射文件也叫做:
Mapper
所以IUserDao也可以叫做IUserDaoMapper是一样的。
2.在IDEA创建目录时,它和包的创建是不一样的
创建包时:cn.itcast.dao是三级目录
目录在创建时:cn.itcast.dao是一级目录
3.Mybatis的映射配置文件位置必须和dao接口的包结构相同
4.映射配置文件的mapper标签属性namespace属性必须是dao接口的全限定类名。
5.映射配置文件的操作配置,id属性的取值必须是dao接口的方法名
2.1.8 mybatis的环境搭建的为什么有这些强制要求?有什么好处呢?
当我们遵从了3.4.5点之后,我们在开发中就无须再写dao的实现类。接口的功能实现
由mybatis来为我们实现。
2.2 mybatis的入门案例
```
public class MybatisTest {
/**
* 入门案例(没写dao实现类)
* @param args
*/
public static void main(String[] args) throws Exception {
//1.读取配置文件:为了将SqlMapConfig中的信息加载出来
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
//它是一个接口,我们用这个SqlSessionFactory工厂,无外乎就是想要创建它的对象。
// 于是Mybatis给我们提供这个工厂的时候,把工厂的创建细节给省略了,
// 为我们准备了SqlSessionFactoryBuilder这个对象,我们用这个对象来构建工厂
// 意思就是:怎么解析配置文件,和我们无关了
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产一个SqlSession对象:为我们提供dao的实现
SqlSession session = factory.openSession();
//没有接口的具体实现,所以我们要想一个办法将它弄出来
//不改变源码的基础上,对已有方法增强---->动态代理
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.释放资源:session对象,in对象
session.close();
in.close();
}
} ```
2.2.2 mybatis的入门步骤小结
1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
3.创建SqlSession对象
SqlSession session = factory.openSession();
4.创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
5.执行dao中的方法
List<User> users = userDao.findAll();
6.释放资源
session.close();
in.close();
注意:
* 不要忘了在映射配置(持久层接口的映射文件IUserDao.xml)中告知mybatis要封
装到哪个实体类。
配置的方式:指定实体类的全限定类名 resultType="cn.itcast.domain.User"
```
<select id="findAll" resultType="cn.itcast.domain.User">
select * from user;
</select>
```
报错:找不到或无法加载主类
* 情况一:
idea本身缓存的问题:IDEA-》file-》invalidate Cache/restart;
* 情况二:
查看structure→modules,其中会包含很多的main,删除掉就行
3、mybatis的框架概述
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需
关注sql语句本身,而不需要花费精力去处理加载驱动,创建连接,创建statement
等繁杂的过程。
mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对
象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架
执行sql并将结果映射为java对象并返回。
持久层接口的映射文件IUserDao.xml有这样一段配置:
<select id="findAll" resultType="cn.itcast.domain.User">
select * from user;
</select>
采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc
api底层访问细节,是我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
3.1 mybatis基于注解方式的案例--annotation
1. 主配置文件:SqlMapConfi.xml保留,
且修改指定指定映射文件的位置为指定配注解的dao位置
```
<mappers>
<!--<mapper resource="cn/itcast/dao/IUserDao.xml"></mapper>-->
<mapper class="cn.itcast.dao.IUserDao"></mapper>
</mappers>
```
2. 持久层接口的映射文件:IUserDao.xml不需要
3. 在持久层接口加上注解:@Select("select * from user")
@Select,并且指定sql语句。
```
public interface IUserDao {
@Select("select * from user")
List<User> findAll();
}
```
4. 虽然可以使用实现类,但是在开发中越简单越好,随意都是不采用dao实现类的方式,
不管使用xml还是注解配置。
尽管mybatis它是支持写dao实现类的。
3.2 不改变原来的方式,来看看dao实现类怎么用
写dao实现类也能实现功能,但是没有意义,增加开发时间。
为了说清楚:namespace和id的作用,我们做这个演示。
```
<mapper namespace="cn.itcast.dao.IUserDao">
<select id="findAll" resultType="cn.itcast.domain.User">
select * from user
</select>
</mapper>
```
因为光靠id无法定位到IUserDao.xml中的Sql语句,需要加上namespace才能找到
sql语句;同理mybatis也要通过namespace和id找到这个sql语句。
* 具体代码演示:参见day0602_mybatis03_daoimpl
4、了解mybatis在应用中的各个过程。
* mybatis入门案例中,设计模式的分析

4.1 mybatis在基于代理dao实现功能(增删改查)的过程中,干了什么事。
4.1.1 组装selectList方法
* 我们在DAO实现类方式中用过该方法
List<User> users = session.selectList("cn.itcast.dao.IUserDao.findAll");

* 这就是整个:
List<User> users = session.selectList("cn.itcast.dao.IUserDao.findAll");所做的事情。
要想让selectList()方法执行,我们需要给方法提供两个信息:
1.连接信息
2.映射信息:两个部分
第一:执行的sql语句
第二:封装结果的实体类的全限定类名。
我们要将这两个信息组合到一起封装,所以说把这两个信息组合起来定义成一个对象(Mapper)

现在我们要组装的信息,第一部分selectList就组装完了。
4.1.2 创建代理对象
我们通过一个方法实现了代理对象的创建
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);

4.1.3 在代理对象中调用selectList方法

5、自定义mybatis
我们不导入mybatis的依赖,自定义一个mybatis
5.1 自定义mybatis能通过入门案例看到的类
package org.apache.ibatis.io; class Resources
package org.apache.ibatis.session; class SqlSessionFactoryBuilder
package org.apache.ibatis.session; interface SqlSessionFactory
package org.apache.ibatis.session; interface SqlSession extends Closeable
这些是我们要自定义的
* 详见项目day0602_mybatis_design