mybatis学习笔记
软件开发常用结构
三层架构
三层架构包含的三层:
界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)
三层的职责:
-
界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和 用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。 主要是和用户打交道,接受用户的的请求参数,显示处理结果的。(jsp,html,servlet)
-
业务逻辑层:接收界面层传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
-
数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交 给业务层,同时将业务层处理的数据保存到数据库.
三层对应的包:
界面层:controller包(servlet...)
业务逻辑层:service包
数据访问层:dao包
三层中类的交互流程:
用户---> 界面层--->业务逻辑层--->数据访问层(持久层)--->DB 数据库(mysql)
三层架构对应的框架:
界面层------------>servelt---------->springmvc(框架)
业务逻辑层------>service类------>spring(框架)
数据访问层------->dao类--------->mybatis(框架)
框架
框架定义
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方 法;另一种认为,框架是可被应用开发者定制的应用骨架、模板。
简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。它定义好了一些基础功能,需要加入自己的功能就是完整的,基础功能是可重复使用的,可升级的。从另一个角度来 说框架一个舞台,你在舞台上做表演。在框架基础上加入你要完成的功能。
框架特点:
1)框架一般不是全能的,不能做所有的事情
2)框架是针对某一个领域有效,特长是在某一个方面,比如mybatis做数据库操作强,但是他不能做其他的
3)框架是一个软件
使用JDBC的缺陷:
1. 代码比较多,开发效率低
2.需要关注 Connection ,Statement, ResultSet 对象创建和销毁
3.对 ResultSet 查询的结果,需要自己封装为 List
4.重复的代码比较多些
5.业务代码和数据库的操作混在一起
MyBatis框架
一个持久层框架,早期叫做ibatis,mybatis是MyBatis SQL Mapper FrameWork for Java(sql映射框架),MyBatis可以操作数据库,对数据进行增删改查,Mybatis可以看做是高级的jdbc,解决jdbc的缺点。
1)sql mapper : sql 映射
可以吧数据库中的一行数据,映射成一个java对象,一行数据可以看做是一个java对象。操作这个对象就相当于操作表中的数据。
2)Data Access Object (DAOs):数据访问
对数据库执行增删改查。
mybatis提供的功能:
0.注册驱动
1.提供了创建Connection,statement,Resultset的能力,不用开发人员创建这个对象了
2.提供了执行sql语句的能力
3.提供了循环sql,把sql结果转换为java对象,List集合的能力。
4.提供了关闭资源的能力,不用自己关闭connection,statement,resultset
开发人员需要做的是:提供sql语句。
流程:开发人员提供sql语句----->mybatis处理sql----->开发人员得到List集合或者java对象(表中的数据)。
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力,增强的jdbc,使用mybatis让开发人员集中精神写sql就行了,不必关心Connection,Statement,ResultSet的创建,销毁,SQL的执行。
MyBatis入门:第一个MyBatis的创建
实现步骤:
1.创建student表(id,name,email,age)
2.新建maven项目
3.修改pom.xml文件
1)加入依赖:MyBatis依赖,mysql依赖,junit依赖
2)在
4.创建实体类Student,定义属性,属性要和student表中的列名保持一致
5.创建Dao接口,定义操作数据库的方法
6.创建xml文件(mapper文件),写sql语句
mybatis框架推荐是把sql语句和java代码分开
mapper文件:定义和dao接口在同一目录,一个表一个mapper文件。
7.创建mybatis的主配置文件(xml文件),有一个,放在resources目录下
1)定义创建连接实例的数据源(DataSource)对象
2)指定其他mapper文件的位置。
8.创建测试的内容
1)可以使用main方法,测试MyBatis访问数据库
2)也可以使用junit访问数据库
概念
1.自动提交:当你的sql语句执行完毕后,提交事务,数据更新操作直接保存到数据库
2.手动提交事务:在需要提交事务的位置,执行方法,提交事务或者回滚事务。
主要的类的介绍
1.Resources:mybatis中的一个类,负责读取主配置文件信息
InputStream in= Resources.getResourceAsStream(config);
2.SqlSessionFactoryBuilder:创建SqlSessionFactory对象,
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory=builder.build(in);
3.SqlSessionFactory:重量级对象,程序创建这个对象耗时比较长,使用资源比较多,在整个项目中,有一个就够了。
SqlSessionFactory:接口,接口实现类:DefaultSqlSessionFactory
SqlSessionFactory作用:获取SqlSession对象,SqlSession sqlSession=factory.openSession();
openSession()方法说明:
1)openSession():无参数的,获取的是非自动提交事务的SqlSession对象
2)openSession(Boolean):openSession(true) 获取自动提交事务的SqlSession
openSession(false)非自动提交事务的SqlSession对象。
4.SqlSession:是一个接口,定义了操作数据的方法,例如selectOne(),selectList(),insert(),update(),delete(),commit(),rollback()。
SqlSession接口的实现类DefaultSqlSession
SqlSession使用要求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close(),这样能保证他的使用是线程安全的。
SqlSession使用步骤:
1.在方法的内部,执行sql语句之前,先获取sqlSession对象
2.调用SqlSession的方法,执行sql语句
3.关闭SqlSession对象,执行SqlSession.close()
SqlSession的作用是提供了大量的执行sql语句的方法:
selectOne:执行sql语句,最多得到一行记录,多余一行是错误的
selectList:执行sql语句,返回多行数据
selectMap:执行sql语句,得到一个Map结果
insert:执行insert语句
update:执行update语句
delete:执行删除语句
commit:提交事务
rollback:回滚事务
dao代理
mybatis提供代理:mybatis创建Dao接口的实现类对象,完成sql语句的执行。mybatis创建一个对象代替你自己的dao实现类功能。
使用mybatis代理要求:
1)mapper文件中的namespace一定是dao接口的全限定名称
2)mapper文件中标签的id是dao接口方法的名称。
mybatis代理实现方式:使用SqlSession对象的方法getMapper(dao.class)
例如:现在有StudentDao接口,接口中有方法selectStudentById,相关代码为:
SqlSession sqlSession=MyBatisUtils.getSession();//MyBtisUtils.getSession()方法为自己写的工具类:获取sqlSession方法的工具类
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student student=dao.selectStudentById(1001);//1001为学生学号
理解参数
理解参数:通过java程序把数据传入到mapper文件中的sql语句,参数主要是指dao接口方法的形参。
parameterType
parameterType表示的是参数的类型,指定dao方法的形参数据类型。这个属性值可以使用java类型的全限定名称或者mybatis定义的别名
dao接口方法是一个简单类型的参数
简单类型:包括java基本数据类型和String
Student selectStudentByEmail(String email);
<select id="selectStudentByEmail" resultType="com.hao.entity.Student">
select id,name,email,age from student where email=#{email}
select>
dao接口方法有多个简单类型的参数
@param:命名参数,在方法的形参前面使用的,定义参数名,这个名称可以用在mapper文件中。
dao接口,方法的定义
/*
多个简单类型的参数
使用@param命名参数,注解是mybatis提供的
使用位置:在形参定义的前面
属性:value自定义的参数名称(不过自定义的名字要与mapper文件中的变量一样)
*/
List<Student> selectStudentsByNameOrAge(
<select id="selectStudentsByNameOrAge" resultType="com.hao.entity.Student">
select id,name,email,age from student where name=#{myname} or age=#{myage}
select>
使用对象作为参数
方法的形参是一个java对象,这个java对象表示多个参数。使用对象的属性值作为参数使用
java对象的定义:
public class Student {
private int id;
private String name;
private String email;
private int age;
具有set和get方法;
}
dao接口:
//按照对象查询学生
ListselectStudentsByObject(Student student);
mapper文件:
任意对象都可以使用,只要有set方法
@Test
public void selectStudentsByObject(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student student=new Student();
student.setAge(18);
student.setName("李白");
Liststudents=dao.selectStudentsByObject(student);
students.forEach(stu-> System.out.println(stu));
sqlSession.close();
}
#和$的区别
#占位符
语法:#{字符}
mybatis处理#{} ,在jdbc中使用的对象是PrepareStatement对象
#{}的特点:
1)使用的PrepareStatement对象,执行sql语句,效率高。
2)使用的PrepareStatement对象,能避免sql语句,SQL语句执行的更安全。
3)#{}常常作为列值使用的,位于等号的右侧,#{}位置的值和数据类型有关的。
$占位符
语法:${字符}
myvatis执行${}占位符的sql语句,在jdbc中相当于使用Statement对象
${}的特点:
1)使用Statement对象执行sql语句,效率低
2)${}占位符的值,使用字符串连接方式,有sql注入的风险,有代码安全的问题
3)${}数据是原样使用的,不会区分数据类型
4)${}常用作表名或者列名,在能保证数据安全的情况下使用${}
封装MyBatis输出结果
封装输出结果:MyBatis执行sql语句,得到Resultset,转为java对象
resultType
resultType属性:在执行select时使用,作为
resultType:表示结果类型,mysql执行sql语句后得到的java对象类型。
1.resultType表示简单类型:
dao方法:
long countStudent();
mapper文件:
2.resultType表示map结构
执行sql得到一个Map数据结构,mybatis执行sql,把ResultSet转为map,
sql执行结果,列名做map的key,列值作为value
sql执行的是一行记录,转为map结构是正确的。
dao接口返回是一个map,sql语句最多能获取一行,多余一行就是错误的
Map
resultType:使用的是java类型的全限定名称,表示的意思是mybatis执行sql,把ResultSet中的数据转为Student类型的对象,MyBatis会做以下的操作:
1:调用com.hao.entity.Student的无参构造方法,创建对象。
Student student =new Student();
2.同名的列赋值给同名的属性
student.setId(rs.getInt("id"));
student.setName(rs.getName("name"));
3.得到java对象,如果dao接口返回的是List集合,mybatis把student对象放入到List集合。
resultMap
resultMap:结果映射,自定义列名和java对象属性的对应关系,常用在列名和属性名不同的情况。
用法:
1.先定义resultMap标签,指定列名和属性名称对应关系
2.在select标签使用resultMap属性,指定上面定义的resultMap的id值
MyBatis自定义别名
mybatis提供的对java类型定义简短,好记名称
自定义别名的步骤:
1)在mybatis主配置文件中,使用typeAliases标签声明别名
2)在mapper文件中,resultType=“别名”
3)声明别名,在主配置文件中声明别名。
第一种语法格式:
type:java类型的全限定名称(自定义类型)
alias:自定义别名
优点:别名可以自定义
缺点:每个类型必须单独定义
第二种语法格式:
name:包名,mybatis会把这个包中所有类名作为别名(不用区分大小写)
优点:使用方便,一次给多个类定义别名
缺点:别名不能自定义,必须是类名,并且如果不同的包下有相同的类名,可能会出现一些错误
数据库的列名和java对象属性名称不一样的解决方式
1)使用resultMap:自定义列名和属性名
2)使用resultType:使用列别名,让别名和java对象属性一样
动态sql
动态sql:同一个dao的方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化。
主要通过使用mybatis提供的标签,实现动态sql的能力,主要学习if,where,foreach,sql,使用动态sql的时候,dao方法的形参使用java对象。
什么情况下使用动态sql:多条件查询的时候使用动态sql。
if标签
语法格式:
sql代码
在mapper文件中:
示例:
ListselectIf(Student student);
Test
@Test
public void testSelectIf(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student student=new Student();
//student.setName("凯");
student.setAge(18);
Listlist=dao.selectIf(student);
list.forEach(stu-> System.out.println(stu));
sqlSession.close();
}
where标签
使用if标签时,容易引起sql语句语法错误,使用where标签解决if产生的语法问题,
使用where标签时,里面是一个或者多个if标签,当有一个if标签判断条件为true,where标签会转为WHERE关键字附加到sql语句的后面,如果if没有一个条件为true,忽略where和里面的if。
语法规则:
sql语句1
sql语句2
foreach
使用foreach可以循环数组,list集合,一般使用在in语句中。
语法格式:
#{item的值}
foreach第一种方式,循环简单类型的List
dao接口:
ListselectForeachOne(List idlist);
映射文件;
测试文件:
@Test
public void testSelectForeachOne(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Listidlist=new ArrayList<>();
idlist.add(1001);
idlist.add(1002);
idlist.add(1003);
Liststudents=dao.selectForeachOne(idlist);
students.forEach(stu-> System.out.println(stu));
sqlSession.close();
}
foreach第一种方式,循环对象类型的List
dao接口:
ListselectForeachTwo(List studentList);
映射文件:
测试文件:
@Test
public void testSelectForeachTwo(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
ListstuList=new ArrayList<>();
Student stu1=new Student();
stu1.setId(1001);
Student stu2=new Student();
stu2.setId(1002);
stuList.add(stu1);
stuList.add(stu2);
Liststudents=dao.selectForeachTwo(stuList);
students.forEach(stu-> System.out.println(stu));
sqlSession.close();
}
sql标签:代码片段
sql标签表示一段sql代码,可以是表名,几个字段,where条件都可以,可以在其他地方复用sql标签的内容,
使用方式:
1)在mapper文件中定义sql代码片段部分sql语句
2)在其他的位置,使用include标签引用某个代码片段
MyBatis配置文件
mybatis配置文件分为两大类:
1)mybatis主配置文件:
提供mybatis全局设置的,包含的内容有:日志,数据源,mapper文件的位置。
2)mybatis的mapper文件。
写sql语句的,一般是一个表一个mapper文件。
settings部分
settings是mybatis的全局设置,影响整个mybatis的运行,这个设置一般使用默认值就可以了。
typeAliase别名
第一种语法格式:
type:java类型的全限定名称(自定义类型)
alias:自定义别名
优点:别名可以自定义
缺点:每个类型必须单独定义
第二种语法格式:
name:包名,mybatis会把这个包中所有类名作为别名(不用区分大小写)
优点:使用方便,一次给多个类定义别名
缺点:别名不能自定义,必须是类名,并且如果不同的包下有相同的类名,可能会出现一些错误
配置环境
environments:环境标签,在它里面可以配置多个environment
属性:default,必须是某个environment的id属性值,表示mybatis默认连接的数据库。
environment:表示一个数据库的连接信息。
属性:id自定义的环境标识,唯一值
transactionManager:事务管理器
属性:type表示事务管理器的类型。
属性值:1)JDBC:使用Connection对象,由mybatis自己完成事务的处理。
2)MANAGED:管理,表示把事务的处理交给容器实现(由其他软件完成事务的提交,回滚)
dataSource:数据源,创建Connection对象,连接数据库。
属性:type数据源的类型
属性值:1)POOLED,mybatis会在内存中创建PooledDataSource类,管理多个Connection连接对象,使用的连接池。
2)UNPOOLED,不使用连接池,mybatis创建一个UnPooledDataSouurce这个类,每次执行sql语句先创建Connection对 象,再执行sql语句,最后关闭连接。
3)JNDI,java的命名和目录服务
使用数据库属性配置文件
需要把数据库的配置信息放到一个单独文件中,独立管理,这个文件扩展名是properties.在这个文件中,使用自定义的key=value的格式表示数据。
使用步骤:
1.在resources目录中,创建xxxx.properties
2.在文件中,使用key=value的格式定义数据
例如:jdbc.url=jdbc:mysql://localhost:3306/springdb
3.在mybatis主配置文件,使用property标签引用外部的属性配置文件
语法:
4.在使用值的位置,使用${key}获取key对应的value(等号右侧的值)
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.username=root
jdbc.password=123456
mapper标签
使用mapper指定其他mapper文件的位置,mapper标签使用的格式有两个常用的方式。
PageHelper
PageHelper做数据分页,在select语句后面加入分页的SQL内容,如果使用的是mysql数据库,他就是在select * from student 后面加入limit语句。
使用步骤:
1)加入PageHelper依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.0version>
dependency>
?
2)在mybatis主配置文件,加入plugin声明
在<environments>之前加入
<plugins>
<plugin interceptor="com.github.pagehelper.PageIntercapter"/>
plugins>
3)在select语句之前,调用PageHelper.startPage(页码,每页大小)
PageHelper.startPage(1,3);