MyBatis
具备的知识
-
java基础
-
-
mysql数据库
-
maven工具
-
xml
环境
-
jdk 1.8
-
Mysql 5.7
-
maven 3.6.1
-
idea
一、MyBatis
1、MyBatis框架是什么?
框架:我们只要按照它的规则编写少量代码和配置就能使用它提供功能。
生活举例:去医院看病填写表格,那张表格就是别人准备好的条条框框
MyBatis是一个持久层的框架
2、持久层
2.1、持久化是什么?
程序里的数据从瞬时状态到持久状态的一个转换过程。
内存:断电即失 磁盘:持久数据
2.2、为什么需要持久化?
-
程序中有些对象不允许丢失
-
内存价格比较昂贵
-
生活举例:冷藏
2.3、持久层是什么?
我们之前学过三层架构
-
dao(数据访问)层
-
service(业务逻辑处理)层、
-
controller(请求控制/处理)层。。。
持久化是一个动作,而dao层是所有完成数据持久化的代码块,层的界限更加的清晰
3、mybatis提供好处
-
支持自定义sql、存储过程以及高级映射。
-
帮我们几乎免除了所有的jdbc代码以及设置参数和获取结果集等工作。
-
可以通过简单xml或注解来配置和映射原始类型、接口、java对象为数据库中的记录。
ORM(对象关系映射,object relational mapping)
java程序 ---------- 数据库 类 ---------- 表 属性 ---------- 字段 对象 ---------- 表记录
4、为什么要学MyBatis?
-
帮助程序员将数据存入数据库中
-
方便,传统的jdbc代码太复杂了,帮助我们简化它。
-
用的人多
优点
-
简单易学(本身就很小很简单,只要2个jar包+一点点配置文件就可以安装上mybatis了)
-
灵活(mybatis不会对现有的程序或数据库加强有任何影响;sql语句都是写在xml配置文件里面,便于统一管理和优化)
-
解除程序代码和sql语句的耦合度
-
提供映射标签,支持对象与数据库字段关系映射
-
提供对象关系映射标签,支持对象关系组建维护(数据库里面1对1、1对多、多对多在mybatis如何配置才能映射到java对象)
-
提供xml标签,支持编写动态sql
5、开始使用MyBatis
5.1、文档
官方文档:https://mybatis.org/mybatis-3/zh/index.html
官方文档是最详细的,任何一个老师讲基本不会比它更详细了,我们老师只能简化它,将重要的提取出来。
5.2、创建一个maven工程
maven仓库地址:https://mvnrepository.com/
告诉同学们去Maven仓库中寻找MyBatis的jar,找到后...
pom.xml中添加 Mybatis 的jar包依赖,如下
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
5.3、创建 mybatis-config.xml 配置文件
-
src/main/resources/mybatis-config.xml 文件大致如下
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING" />
settings>
<typeAliases>
<package name="扫描指定报名"/>
typeAliases>
<environments default="oracle">
<environment id="oracle">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@ip地址:端口号:SID"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="映射文件路径"/>
mappers>
configuration>
配置文件讲解顺序如下
-
连接数据库的环境配置
-
事物配置
-
type属性
-
JDBC--告诉mybatis 使用jdbc提供的 事物 控制 (提交、回滚)
-
MANAGED--事物的控制 交给j2ee容器来管理
-
-
-
数据源配置
-
type属性
-
POOLED:使用连接池的方式来管理 连接对象
-
UNPOOLED:不使用连接池的方式来管理
-
JNDI:在j2ee容器中配置我们的数据源(没用过)
-
-
备注:不用oracle驱动jar的话不用管这个
maven安装本地jar到本地maven仓库中的命令
mvn install:install-file -Dfile=jar包的绝对路径 -Dpackaging=文件打包方式 -DgroupId=groupid名 -DartifactId=artifactId名 -Dversion=jar版本
示例
mvn install:install-file -Dfile=D:\develop\database\install\Oracle\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar -Dpackaging=jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0
5.4、编写java类,在main方法中初始化MyBatis
核心代码:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(xxx)
main方法中示例:
public static void main(String[] args) throws IOException {
//获得 类路径下的 mybatis-config.xml 配置文件输入流
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//让mybatis根据配置文件 来初始化 session 工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//得到和数据库 交流的 会话对象
SqlSession session = factory.openSession();
?
System.out.println("===================和数据库会话的对象:"+session);
?
//TODO 对数据库进行操作
//....
//....
//关闭会话
session.close();
//关闭文件输入流
in.close();
?
}
5.5、使用MyBatis操作数据库
5.5.1、简单查询示例
-
映射器配置。建立映射的mapper文件,配置sql语句,xml文件大致如下
-
mybatis-config.xml中引入mapper文件
...
<mappers>
<mapper resource="./mapper/StudentMapper.xml"/>
mappers>
...
-
java代码调用mapper中的sql片段
//mapper的命名空间 点 sql块id
List<Student> list = session.selectList("com.hr.mapper.StudentMapper.selectAll");
-
讲述映射规则, mybatis-config.xml开启驼峰命名规则映射。讲述数据库字段与类名属性要注意的地方
-
没有看到控制台打印sql语句怎么办?mybatis-config.xml中开启日志配置。
5.6、抽取MyBatis公共代码,封装MyBatisUtils类
参考代码如下:
public class MybatisUtils {
static SqlSessionFactory factory = null;
static {
//获得 类路径下的 mybatis-config.xml 配置文件输入流
InputStream in = null;
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
//让mybatis根据配置文件 来初始化 session 工厂
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取session
* @return
*/
public static SqlSession getSession() {
//如果为true,表示 自动比较事物 ,false 不会自动提交
// factory.openSession(true)
//无参的话 就是 false
return factory.openSession();
}
/**
* 关闭session
* @param session
*/
public static void closeSession(SqlSession session) {
if(session != null) {
session.close();
}
}
}
5.6、接口映射
5.6.1、接口与mapper文件之间的关系
-
命名空间 --- 接口的完整类名
-
sqlId --- 接口中定义的方法名
XML示例
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
...
接口示例
package com.zd.dao;
/**
* 操作student表的dao层接口
*/
public interface StudentDao {
...
}
5.6.2、接口的方式示例 增、删、改、查
这个过程将演示和说明的内容如下
参数获取的方式有
-
#{}--- 占位符,我们以前写的sql语句中的 ?。即:动态解析--->sql预编译--->执行sql。能防止sql注入 -
${}--- 拼接符,拼接字符串生成sql语句。即:动态解析--->sql编辑--->执行sql。不能防止sql注入,很少用
别名定义
-
mybatis-config.xml中
可以为实体类定义别名 -
此外,mybatis也默认定义了一系列别名,可在
TypeAliasRegistry.class中查看
XML中常见的转义符
& &
< <
> >
" "
' '
]]>
多个对象参数传递
xml配置
调用的java代码
...
//条件
Student stu = new Student();
stu.setStuName("张");
//调用查询
Listlist = stuDao.queryStuList(1,stu);
...
5.7、结果集映射
-
结果集映射标签-
实体类构造标签
-
-
-
标签 --- 单个对象关联 -
--- 集合关联-
fetchType:"lazy" 懒加载
-
-
示例1:
示例2:多对一 / 一对多 映射配置
type="com.zd.entity.Student">
column="c_id" select="com.zd.dao.ClzDao.queryClzById"/>
column="id" fetchType="lazy"
select="com.zd.dao.StudentDao.queryStuList" />
5.8、MyBatis常用注解
5.8.1、@Alias 别名注解
@Alias("Clzz")
public class Clzz {
...
}
5.8.2、@Select 查询注解、@Param 参数注解
public interface TeacterMapper {
@Select(value = "select * from teacher ")
public List selectList();
@Select(value = "select * from teacher where id = #{identity}")
public Teacher selectById(@Param(value = "identity") Integer id);
}
5.8.3、@Insert、@Update、@Delete
下面只示例了 @Insert, @Update、@Delete 同学们依葫芦画瓢即可
public interface TeacterMapper {
@Insert("insert into teacher values(#{tea.id},#{tea.name})")
public void insert(@Param("tea") Teacher tea);
}
5.8.8、@Results 结果映射注解
一般配合如下注解使用
-
@Result
-
@Many 多个关联对象注解(通常注解在集合上)
-
@One 单个关联注解
public interface TeacterMapper {
@Results(id = "TeaRes",value = {
@Result(column = "tea_id",property = "id"),
@Result(column = "tea_name",property = "name"),
@Result(property = "clsList",
column = "tea_id",
many = @Many(fetchType = FetchType.LAZY,select = "selectClsListByTeaId")
),
@Result(property = "sch",
column = "s_id",
one = @One(fetchType = FetchType.LAZY,
select = "com.hr.mapper.SchoolMapper.selectByid"))
})
@Select(value = "select id tea_id,name tea_name,s_id from teacher ")
public List queryListUseResults();
}
5.9、MyBatis缓存配置
5.9.1、本地缓存(又称一级缓存)
一个会话中的数据进行缓存。默认为打开状态。
可以向同学们示例,在一个Session中反复调用同一个查询多次,结果只有第一次调用时发出了sql语句,后面的都是获取的缓存数据。
代码演示:
5.9.2、二级缓存(也是全局缓存)
在mapper文件中加入 ,就会打开二级缓存, 所有的select 语句都会被缓存,所有的 insert、update、delete会刷新缓存
代码演示:
5.9.3、如何引用其他命名空间(mapper)的缓存配置?
5.9.4、如何具体控制到 select、inert、update、delete 标签上的缓存
以上4个标签都具备useCache属性:
-
useCache:将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true,其他为false
select 标签还有一个能控制缓存的属性:
-
flushCache:将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存刷新,默认值 false。
5.10、MyBatis动态sql
-
if --- 条件判断
-
choose ...when...otherwise --- 相当于java中的 if...else if ...else...
-
trim --- 去掉多余的 两端多余的字符
-
where --- 用于where子句时
-
set --- 用于update语句时
-
foreach --- 循环遍历集合
-
bind ---创建一个变量,绑定到 标签局部环境之中。该变量值支持 OGNL 表达式.(可以理解为在方法里面定义了一个变量)
-
OGNL表达式:支持 +-*/运算,支持简单的对象方法调用...
-
示例1: if、where、set、foreach、choose ...when...otherwise
update student
stu_name = #{stu.stuName},
stu_sex = #{stu.stuSex},
where id = #{stu.id}
示例2:trim
-
加入我现在有这样一条sql语句
-
如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:
SELECT * FROM BLOG WHERE
-
如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
SELECT * FROM BLOG
WHERE
AND title like 'someTitle'
-
我们可以用where标签来解决这个问题,where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
-
trim标签也可以完成相同的功能,写法如下
示例3: bind
5.11、MyBatis 通用Mapper
5.11.1、tk MyBatis
TKMybatis 是基于 Mybatis 框架开发的一个工具,内部实现了对单表的基本数据操作,只需要简单继承 TKMybatis 提供的接口,就能够实现无需编写任何 sql 即能完成单表操作。
官网:https://github.com/godlike110/tk-mybatis
5.11.1.2、使用
-
pom.xml中加入依赖
tk.mybatis
mapper
4.1.5
-
集成mybatis核心代码
//创建一个MapperHelper
MapperHelper mapperHelper = new MapperHelper();
//让插件装载mybatis配置
mapperHelper.processConfiguration(session.getConfiguration());
-
常用注解
-
@Table(name = "表名") //此注解一般打在实体类上,用于表明此实体类映射的数据库表名是 xxx
-
@Id //此注解一般打在实体类的字段上,用于表明此字段 映射的是ID列
-
@Column(name="数据库列名") //此注解一般打在实体类的字段上,用于表明此字段 映射的是列名是xxx
-
@ColumnType(jdbcType = JdbcType.DATE) //此注解一般打在实体类的字段上,用于表明此字段对应的数据库类型
-
@KeySql(sql = "select student_seq.nextval from dual",order = ORDER.BEFORE) //此注解在遇到需要通过select语句获取id时使用
-
-
组装条件部分代码示例
//指定构造student的条件
Example condition = new Example(Student.class);
//创建组装条件的对象(criteria[kra?'t??ri?] 标准/原则), 之后开始组装
condition.createCriteria().andEqualTo("height", "170").andLike("name", "%张三%");
//根据id列排序
condition.orderBy("id");
5.11.1.3、完整示例
-
实体类 Student 定义如下
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
/**
* 映射 student表的实体类
*/
//告诉mybatis 通用mapper插件,我这个实体类对应的对应的是 t_student
@Table(name = "t_student")
public class Student implements Serializable {
//主键
//告诉tk mybats 通用mapper插件这个字段是主键
@Id
private Integer id;
//学生的名字
private String stuName;
//年龄
private Integer stuAge;
//分数
private Double stuScore;
//出生日期
private Date stuBirthday;
//性别
private String stuSex;
//这个学生所属的班级
private Clz clz;
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Integer getStuAge() {
System.out.println("调用了 getStuAge方法....");
return stuAge;
}
public void setStuAge(Integer stuAge) {
this.stuAge = stuAge;
}
public Double getStuScore() {
return stuScore;
}
public void setStuScore(Double stuScore) {
this.stuScore = stuScore;
}
public Date getStuBirthday() {
return stuBirthday;
}
public void setStuBirthday(Date stuBirthday) {
this.stuBirthday = stuBirthday;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public Clz getClz() {
return clz;
}
public void setClz(Clz clz) {
this.clz = clz;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", stuName='" + stuName + '\'' +
", stuAge=" + stuAge +
", stuScore=" + stuScore +
", stuBirthday=" + stuBirthday +
", stuSex='" + stuSex + '\'' +
", clz=" + clz +
'}';
}
public Student(Integer id, String stuName, Integer stuAge, Double stuScore, Date stuBirthday, String stuSex) {
this.id = id;
this.stuName = stuName;
this.stuAge = stuAge;
this.stuScore = stuScore;
this.stuBirthday = stuBirthday;
this.stuSex = stuSex;
}
}
-
操作t_student表的mapper接口定义如下
import com.zd.entity.Student;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
/**
* 操作student表的dao层接口
*/
public interface StudentMapper extends Mapper{
/**
* 自定义较为复杂的查询
* @return
*/
ListqueryList();
}
-
测试
import com.zd.entity.Student;
import com.zd.mapper.StudentMapper;
import com.zd.utils.DateUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.RowBoundsMapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class MybatisTest {
public static void main(String[] args) throws IOException {
//创建session对象的工厂
SqlSessionFactory factory = getSqlSessionFactory();
//搞第一个session对象出来
SqlSession session = factory.openSession();
//初始化(集成) 通用mapper的配置
initCommonMapperConfig(session);
//测试通用mapper的方法
testCommonMappe(session);
/*
*用完这个和数据库交流的回话之后呢,一定要 关闭/释放它.
* 将其修改为空闲的状态。
* 和 Connection.close概念是不一样的。
*/
session.close();
}
/**
* 初始化通用mapper的配置
*
* @param session
*/
public static void initCommonMapperConfig(SqlSession session) {
//创建一个MapperHelper
MapperHelper mapperHelper = new MapperHelper();
/*
可省略的配置---begin
*/
//特殊配置
Config config = new Config();
//主键自增回写方法,默认值MYSQL,详细说明请看文档
config.setIDENTITY("MYSQL");
//支持getter和setter方法上的注解
config.setEnableMethodAnnotation(true);
//设置 insert 和 update 中,是否判断字符串类型!=''
config.setNotEmpty(true);
//校验Example中的类型和最终调用时Mapper的泛型是否一致
config.setCheckExampleEntityClass(true);
//启用简单类型
config.setUseSimpleType(true);
//枚举按简单类型处理
config.setEnumAsSimpleType(true);
//自动处理关键字 - mysql
config.setWrapKeyword("`{0}`");
//设置配置
mapperHelper.setConfig(config);
/*
可省略的配置---end
*/
//注册通用接口,和其他集成方式中的 mappers 参数作用相同
//4.0 之后的版本,如果类似 Mapper.class 这样的基础接口带有 @RegisterMapper 注解,就不必在这里注册
mapperHelper.registerMapper(Mapper.class);
//配置 mapperHelper 后,执行下面的操作
mapperHelper.processConfiguration(session.getConfiguration());
}
/**
* 获取 SqlSessionFactory
*
* @return
*/
public static SqlSessionFactory getSqlSessionFactory() {
InputStream input = null;
SqlSessionFactory factory = null;
try {
input =
MybatisTest.class
//获取类加载器
.getClassLoader()
//获取对应类信息目录下的文件输入流
.getResourceAsStream("mybatis-conf.xml");
/**
* mybatis用的是 工厂设计模式
*/
//session工厂构建器
SqlSessionFactoryBuilder builder =
new SqlSessionFactoryBuilder();
//利用这个工厂的构建器 去创建一个session工厂
factory = builder.build(input);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
//关闭文件的输入流
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return factory;
}
/**
* 获取操作数据的 session对象
*
* @return
*/
public static SqlSession getSqlSession() {
//利用这个工厂获取一个空闲的session
SqlSessionFactory factory = getSqlSessionFactory();
//获取了一个 打开了事物的 session
SqlSession session = factory.openSession();
return session;
}
/**
* 测试通用mapper的方法
* @param session
*/
public static void testCommonMappe(SqlSession session) {
//操作student表的接口
StudentMapper mapper = session.getMapper(StudentMapper.class);
// Listlist = mapper.selectAll();
//以前的那种写法是否支持测试
// Listlist = mapper.queryList();
// System.out.println(list);
//测试 通用mapper添加
Student stu = new Student(
8, "大丁丁", null,
null, null, null);
// int i = mapper.insert(stu);
// System.out.println("插入后返回的是什么呢?---"+i);
// mapper.delete(new Student());
//修改全部的字段,排除主键
// mapper.updateByPrimaryKey(stu);
//只修改不为null的字段
// mapper.updateByPrimaryKeySelective(stu);
/*
*example 条件示例
*/
Example example = new Example(Student.class);
//利用这个example创建一个标准的条件对象
example.createCriteria()
// = 匹配
.andEqualTo("id", 3)
// and 连接
// .andEqualTo("stuSex","女")
.orEqualTo("stuSex","女")
;
//将条件交给它
mapper.selectByExample(example);
//分页查询
//条件参数
Student s1 = new Student();
s1.setStuSex("女");
//分页参数
int current = 2;//当前页
int size = 3; //每页显示数量
RowBounds bounds = new RowBounds((current - 1)* size,size);
Liststus = mapper.selectByRowBounds(s1, bounds);
//当你看到日志中获取的结果集没有分页时不要怀疑,没有问题的。
//mybatis自带的分页是基于内存的一种分页方式,你只要看到最后获取的结果集是正确的就可以了
System.out.println("分页之后的数据-----------size:"+stus.size());
System.out.println(stus);
//提交事物
// session.commit();
}
}
5.11.2、MyBatis Plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
注:mybatis plus 必须配合spring 容器来使用。
搜索
复制