第一章 框架的概述
1.1 三层架构
- mvc
mvc:web中使用mvc架构模式。m:数据。v:试图。c:控制器
c控制器:接受请求,调用service对象,显示请求的处理结果。当前使用servlet作为控制器。
v视图:显示请求的处理结果。把m中的数据显示出来。
m数据:来自数据库MySQL,来自文件,来自网络。
mvc作用:
1)实现解耦合;
2)让mvc各负其职;
3)使得系统拓展性更好,更容易维护。
- 三层架构:
-
界面层(视图层):接受用户的请求,调用service,显示请求的结果,包含了jsp,html,servlet等对象。
-
业务逻辑层:处理业务的逻辑,使用算法处理数据,把数据返回给界面层。对应的包是service,和包中的很多XXXService类。
-
持久层(数据库访问层):访问数据库,或者读取文件,访问网络。获取数据,对应的包是dao。
1.2 三层架构请求的处理流程
用户发起请求—>界面层—>业务逻辑层—>持久层—>数据库(mysql)
1.3 为什么使用三层架构
-
结构清晰、耦合度低,各层分工明显
-
可维护高,可拓展性高
-
有利于标准化
-
开发人员可以只关注整个结构中的某一层的功能实现
-
有利于各层逻辑的复用
1.4 三层架构模式和框架
-
每一层对应着一个框架
-
界面层—SpringMvc框架
-
业务层—Spring框架
-
持久层—MyBatis框架
-
1.5 框架
- 什么是框架(framework)
框架:就是一个软件,完成了部分的功能。软件中的类和类之间的方法调用已经规定好了。通过这些可以完成某些功能。框架看做是模板。
框架是可以升级的、可以改造的。框架是安全的。
框架是对某一方面是有用的,不是全能的。
1.6 框架解决的问题
- 框架能实现技术的整合。
- 提高开发的效率,降低难度。
1.7jdbc访问数据库的优缺点
- 优点
- 直观,好理解
- 缺点
- 需要创建很多对象
- 注册驱动
- 执行SQL语句
- 把resultSet转为对象、LIst集合
- 关闭资源
- SQL语句和业务逻辑代码混在一起
1.8MyBatis框架
- 什么是mybatis
是一个持久层框架,原名ibatis,2013改名为mybatis,mybatis可以操作数据库,对数据执行增删改查。看做是高级的jdbc。解决jdbc的缺点
- mybatis能做什么?
- 注册驱动
- 创建jdbc中使用的Connection,Statement,ResultSet
- 执行sql语句,得到ResultSet
- 处理ResultSet,把记录集中数据转为Java对象,同时把Java对象放到List集合
- 关闭资源
- 实现sql语句和Java代码的解耦合
*mybatis的官网:http://mybatis.org/mybatis-3/
第二章 Mybatis入门
2.1第一个例子
- 新建maven项目
- 修改pom.xml
- 加入依赖。 mybatis依赖,MySQL驱动,Junit
- 在中加入资源插件
- 创建实体类。定义属性---------属性名和列名保持一致
- 创建Dao接口,定义数据库的方法
- 创建xml文件(mapper文件),写SQL语句
mybatis框架推荐是把SQL语句和Java代码分开
mapper文件:定义和dao接口在同一目录,一个表一个mapper文件。
- 创建mybatis的主文件(xml文件):只有一个,放在resource目录下
- 定义创建连接实例的数据源(DataSource)对象
- 指定其他的mapper文件位置
- 创建测试的内容
- 使用main方法,测试mybatis访问数据库
- 也可以使用Junit访问数据库
2.2概念
- 自动提交:当你的SQL语句执行完毕后,提交事务。数据库更新操作后保存数据
- 手动(手工)提交事务:在你需要提交事务的位置,执行方法,提交事务或者回滚事务。
2.3mybatis的一些重要对象
- Resource::读取主配置信息。
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
- SqlSessionFactoryBuilder:负责创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
- SqlSessionFactory
-
SqlSessionFactory是重量级对象:创建此对象需要使用更多的资源和时间。在项目中有一个就可以!
-
SqlSessionFactory接口:作用是SqlSession的工厂,就是创建SqlSession对象。
-
DefaultSqlSessionFactory实现类
public class DefaultSqlSessionFactory implements SqlSessionFactory { }
- SqlSessionFactory接口中的方法
- openSession():获取一个默认的openSession对象,默认是需要手工提交事务。
- true:创建一个自动提交事务的SqlSession
- false:等同于无参openSession()。
- openSession():获取一个默认的openSession对象,默认是需要手工提交事务。
- SqlSession
SqlSession对象是通过SqlSessionFactory获取的。SqlSession本身是接口
DefaultSqlSessionFactory:实现类
public class DefaultSqlSessionFactory implements SqlSessionFactory { }
提供了大量执行SQL语句的方法:
selectOne:执行SQL语句最多返回一条数据
selectList:执行SQL语句返回多条数据
selectMap:执行SQL语句得到一个map
insert:执行insert语句
update:执行update语句
delete:执行delete语句
commit:提交事务
rollback:回滚事务
注意:SqlSession对象不是线程安全的,使用步骤:
- 在方法的内部,执行SQL语句之前,先获取SqlSession对象
- 调用SqlSession的方法,执行SQL语句
- 关闭SqlSession对象,执行SqlSession.close()
保证SqlSession是局部变量
2.4使用工具类和模板
- 创建模板。mapper模板+mybatis主配置模板
创建模板文件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4GxRRLOp-1684751215913)(C:\Users\22284\AppData\Roaming\Typora\typora-user-images\image-20220303224848697.png)]
创建文件选择使用的模板:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fcaT6cL3-1684751215921)(C:\Users\22284\AppData\Roaming\Typora\typora-user-images\image-20220303225035996.png)]
第三章 Mybatis的Dao代理
3.1 dao代理
3.1.1 mybatis提供代理:
mybatis创建Dao接口的实现类对象,完成对sql语句的执行。mybatis创建一个对象代替你的dao实现类功能。
3.1.2 使用mybatis代理的要求
- mapper文件中的namespace:必须是dao接口的全限定名称
- mapper文件中标签的id是dao接口的方法名
3.1.3 mybatis代理的实现方式
使用SqlSession对象的方法getMapper(dao.class)。
例如:现在有StudentDao接口
SqlSession session = MyBatisUtil.getSqlSession(); StudentDao dao = session.getMapper(StudentDao.class); Student student = dao.selectStudentById(1);
3.2 理解参数
理解参数是:通过Java程序把数据传入到mapper文件的sql语句。参数主要是指dao接口的形参
3.2.1 paramterType
- paramterType:表示参数的类型,指定dao方法的形参数据类型。这个形参的数据类型是给mybatis使用。**–>**mybatis在给sql语句的参数赋值时使用。PrepareStatement,setXXX( 位置 , 值 )
第一个用法:Java类型的全限定名称 parameterType="java.lang.Integer"
第二个用法:mybatis定义的Java类型的别名 parameterType="int"
parameterType:mybatis通过反射机可以获取 dao 接口方法参数的类型,可以不写
<select id="selectBYId" parameterType="integer" resultType="deping.study.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
3.2.2 dao接口是一个简单类型的参数
//dao接口的形参是一个简单类型
//简单类型:Java基本数据类型和String
Student selectByEmail (String email);
<!--
dao接口是一个简单类型的参数
mapper文件,获取这个参数,使用#{任意字符}
-->
<select id="selectByEmail" resultType="deping.study.domain.Student">
select id,name,email,age from student where email=#{studentEmail}
</select>
3.2.3 dao接口方法有多个简单类型的参数
@Param:命名参数,在方法的形参面前使用,定义参数名。这个名称可以用在mapper文件中。
dao接口定义:
/*
多个简单类型的参数
使用@Param命名参数,注解是mybatis提供的
位置:在形参定义的前面
属性:value自定义的参数名称
*/
List<Student> selectByNameOrAge(@Param("mynane") String name, @Param("myage") Integer age);
mapper文件:
<!--
多个简单类型的参数
当使用@Param命名参数后,例如@Param("mynane")
在mapper中,使用#{命名的参数},例如 #{myname}
-->
<select id="selectByEmail" resultType="deping.study.domain.Student">
select id,name,email,age from student where name=#{myname} or age=#{myage}
</select>
3.2.4 dao接口方法使用一个对象作为参数
对象有属性,有对应的get、set 方法
3.2.5 dao接口方法有多个简单类型的参数,使用位置
参数位置:dao接口中方法的形参列表,从左往右,参数位置是0,1,2,…
语法格式:#{arg0},#{arg1}
mybatis版本 --> 3.5.1
<select id="selectByEmail" resultType="deping.study.domain.Student">
select id,name,email,age from student where name=#{arg0} or age=#{arg1}
</select>
3.2.6 dao接口参数是一个map
使用key获取参数值
语法格式:#{key}
3.3 # 和 $ 的区别
3.3.1 # 占位符
- 语法:#{字符}
<select id="selectBYId" parameterType="integer" resultType="deping.study.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
//mybatis创建PrepareStatement对象,执行sql语句
String sql = " select id,name,email,age from student where id=? ";
PrepareStatement pst = conn.prepareStatement(sql);
pst.setInt(1,值); //传递参数
ResultSet rs = pst.executeQuery(); //执行sql语句
- #{}特点:
- 使用PrepareStatement对象,执行sql语句,效率高。
- 使用PrepareStatement对象,能够避免sql注入;
- #{} 常常作为列值使用,位于等号的右侧,#{}位置的值和数据类型有关。
3.3.2 $占位符
- 语法:${字符}
mybatis执行${}占位符的sql语句
<select id="selectBYId" parameterType="integer" resultType="deping.study.domain.Student"> select id,name,email,age from student where id=${studentId} </select> //${} 表示 字符串连接,把sql语句的其他内容和 ${}内容使用的字符串('+')链接在一起. String sql = " select id,name,email,age from student where id= " + "值"; //mybatis创建Statement对象,执行sql语句 Statement stmt = conn.creatStatement(sql); ResultSet rs = stmt.executeQuery(); //执行sql语句
- ${}特点:
- 使用Statement对象,执行sql语句,效率低。
- ${}占位符的值,使用字符串连接的方式,有sql注入的风险。有代码安全的风险;
- ${}数据是原样使用的,不会区分数据类型;
- 常用作 ∗ ∗ 表名或列名 ∗ ∗ ,在能保证数据安全的情况下使用 {}常用作**表名或列名**,在能保证数据安全的情况下使用 常用作∗∗表名或列名∗∗,在能保证数据安全的情况下使用{}。
3.4 封装MyBatis输出结果
3.4.1 ResultType
resultType属性:在执行select时使用,作为标签的属性出线。
- resultType表示结果类型,mysql执行sql语句,得到Java对象类型的对象。它的值有两种:
1)java类型的全限定名称; 2)使用别名
Student selectBYId(Integer id);
<select id="selectById" parameterType="integer" resultType="deping.study.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
resultType:现在使用Java类型的全限定名称。表示是意思是mybatis执行sql,把resultSet中的数据转为Student类型的对象。
mybatis会做一下操作:
1.调用deping.study.domain.Student的无参构造方法,创建对象。
Student student = new Student(); //使用反射创建对象
2.同名的列赋值给同名的属性。
student.setId( rs.getInt("id") );
student.setName( rs.setString("name") );
3.得到Java对象,如果dao接口的返回值是List集合, mybatis会把student对象放入到List集合。
所以执行 Student mystu = dao.selectById(1); 得到数据库中的 id=1 这行的数据,这行数据的列值赋给了mystu对象的属性。你能得到mystu对象,就相当于是 id=1 这行数据。
- resultType表示简单类型
<select id="SelectCount" resultType="java.lang.Long">
select cout(*) from student
</select>
- resultType表示Map
最多只能返回一行数据
<!--
执行sql语句得到一个map结构,列名作key,列值做value
sql执行得到的是一处记录,转为map结构是正确的。
-->
<select id="selectMap" resultType="java.util.Map">
select id,name from student where id=#{id}
</select>
3.4.2 ResultMap
***resultMap:结果映射。自定义列名和 Java对象的对应关系。***常用在列名和属性名不同的情况下。
用法:
- 先定义 resultMap 标签,指定列名和属性名的对应关系;
- 在select标签使用resultMap 属性,指定上边定义的resultMap 的id值。
<resultMap id="customMap" type="deping.study.domain.Student">
<!--定义列名和属性名的对应关系-->
<!--主键类型使用id标签-->
<id column="id" propery="cid"/>
<!--非主键类型使用result标签-->
<id column="name" propery="cname"/>
<!--列名和属性名相同可以不定义-->
<id column="email" propery="email"/>
<id column="age" propery="age"/>
</resultMap>
<select id="selectById" resultMap="customMap">
select id,name,email,age from student where id=#{studentId}
</select>
3.5 自定义别名
mybatis提供的对Java类型定义的简短、好的的名称。
-
自定义别名的步骤:
- 在mybatis主配置文件中,使用typeAliases标签声明别名;
- 在mapper文件中,resultType=”别名“。
声明别名(mybatis主配置文件)
<!--声明别名--> <typeAliases> <!-- 第一种语法格式: type:Java类型的全限定名称(一般是自定义类型) alias:自定义别名 优点:别名可以自定义 缺点:每个类型必须单独定义 --> <typeAlias type="deping.study.domain.Student" alias="stu" /> <!-- 第二种语法格式: name:包名。 mybatis会把这个包中所有类名作为别名(不区分大小写) 优点:使用方便,一次性给多个类型定义别名 缺点:别名不能自定义,必须是类名 --> <packade name="deping.study.domain"/> </typeAliases>
mapper文件
//resultType="别名"
<select id="selectBYId" parameterType="integer" resultType="stu">
select id,name,email,age from student where id=#{studentId}
</select>
3.6 列名和Java对象的属性名称不一致的解决方式
- 使用resultMap:自定义列名和属性名的对应关系
- 使用resultType:使用列的别名与Java对象的属性名相同
3.7 like
- 第一种方式:在Java程序中,把like的内容组装好,传给sql语句
- 第二种方式:在sql语句中,组织like的内容。
sql语句like的格式: where name like “%” 空格#{name}空格"%"
<select id="selecNameLike" resultType="deping.study.domain.Student">
select * from student where name like "%" #{name} "%"
</select>
第四章 动态SQL
定义:同一个dao方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化。
使用mybatis提供的标签,实现动态sql的能力。主要是if , where , foreach , sql。
多使用在多条件查询语句中。
使用动态sql的时候,dao方法的形参使用Java对象。
😊在mapper的动态SQL中若出现大于号(>)、小于号(<)、大于等于号(>=)、小于等于号(<=)等符号,最好将其装换为实体符号。否则xml可能会出现解析问题。
< 小于 < > 大于 > >= 大于等于 >= <= 小于等于 <=
4.1 if标签
- 语法:
<if test="条件1">
sql代码1
</if>
<if test="条件2">
sql代码2
</if>
例子:
<select id="select_if" resultType="deping.study.domain.Student">
select * from student
where 1=1
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age > 0">
and age = #{age}
</if>
</select>
4.2 where标签
使用if标签时,容易引起sql语句的语法错误。使用where标签能够解决if产生的语法问题。
使用时 where,里面是一个或多个if标签,当有一个if标签判断条件为true时,where标签会转为WHERE关键字附加到sql语句的后面。如果if没有一个条件为true,忽略where和里面的if
where标签会删除离它最近的 or 或者 and 。
- 语法
<where>
<if test="条件1">
sql代码1
</if>
<if test="条件2">
sql代码2
</if>
</where>
例子:
<select id="select_where" resultType="deping.study.domain.Student">
select * from student
<where>
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age > 0">
and age = #{age}
</if>
</where>
</select>
4.3 foreach标签
使用foreach可以循环数组、list集合,一般用在 in 语句中。
- 语法
<foreach collection="集合类型" open="开始的字符" close="结束的字符"
item="集合中的成员" separator="集合成员之间的分割符">
#{item 的值}
</foreach>
- 标签属性
- collection:表示循环对象的类型。 数组–>collection=“array” 集合–>collection=“list”
- open:循环开始时的字符。
- close:循环结束时的字符。
- item:集合成员,自定义的变量。
- separator:集合成员之间的分割符。
- #{item 的值}:获取集合成员的值。
4.3.1 遍历List<简单类型>
List<Student> select_foreach1(List<Integer> list);
<select id="select_foreach1" resultType="deping.study.domain.Student">
select * from student
<if test="list != null and list.size>0">
where id in
<foreach collection="list" open="(" close=")" item="myid" separator=",">
#{myid}
</foreach>
</if>
</select>
4.3.2 遍历<对象类型>
List<Student> select_foreach2(List<Student> list);
<select id="select_foreach2" resultType="deping.study.domain.Student">
select * from student
<if test="list != null and list.size>0">
where id in
<foreach collection="list" open="(" close=")" item="stu" separator=",">
#{stu.id}
</foreach>
</if>
</select>
4.4 sql标签
sql标签表示一段sql代码,可以是表名、几个字段、where条件等,可以在其他地方复用sql标签的内容。
- 使用方式:
- 在mapper文件中定义 sql代码片段 部分SQL语句
- 在其他的位置,使用include标签引用某个代码片段
例如:
<!--定义代码片段-->
<sql id="selectStudent"> select * from student </sql>
<!--引用(复用)代码片段-->
<select id="select_foreach2" resultType="deping.study.domain.Student">
<include refid="selectStudent" />
<if test="list != null and list.size>0">
where id in
<foreach collection="list" open="(" close=")" item="stu" separator=",">
#{stu.id}
</foreach>
</if>
</select>
第五章 MyBatis配置文件
mybatis配置文件两大类:
- mybatis主配置文件:提供mybatis的全局设置。包含的内容:日志、数据源、mapper文件位置。
- mybatis的mapper文件:写sql语句。一个表一个mapper文件。
5.1 setting部分
setting是mybatis的全局设置,影响整个mybatis的运行。这个设置一般使用默认值就可以。
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
例如:
<!--设置日志 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
5.2 别名
设置别名
<!--声明别名-->
<typeAliases>
<!--
第一种语法格式:
type:Java类型的全限定名称(一般是自定义类型)
alias:自定义别名
优点:别名可以自定义
缺点:每个类型必须单独定义
-->
<typeAlias type="deping.study.domain.Student" alias="stu" />
<!--
第二种语法格式:
name:包名。 mybatis会把这个包中所有类名作为别名(不区分大小写)
优点:使用方便,一次性给多个类型定义别名
缺点:别名不能自定义,必须是类名
-->
<packade name="deping.study.domain"/>
</typeAliases>
5.3 配置环境
-
environments:环境标签,在里边可以配置对个environment。
- 属性-default:必须是某个environment的id属性值。
-
environment:表示一个数据库连接信息。
- 属性-id:自定义的环境标识,唯一性。
-
transactionManager:事务管理器
- 属性-type:表示事务管理器的类型。
- 属性值-JDBC:使用Connection对象,由MyBatis自己完成事务的处理。
- 属性值-MANAGE:管理,表示把事务的处理交给容器实现(由其他软件完成事务的提交、回滚)
- 属性-type:表示事务管理器的类型。
-
dataSource:数据源,创建Connection对象,连接数据库。
- type:数据源类型。
- 属性值-POOLED:mybatis自己会在内存中创建PolledDataSource类,管理多个Connection连接,使用的是连接池。
- 属性值-UNPOOLED:不使用连接池。mybatis创建一个UnPolledDataSource这个类,每次执行sql语句先创建Connection对象,再执行sql语句,最后关闭Connection。
- 属性值-JNDI:Java的命名和目录服务。
- type:数据源类型。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置数据源: 创建Connection对象-->
<dataSource type="POOLED">
<!-- driver: 驱动的内容-->
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- url: 连接数据库的URL 注意:html 标签实体-->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis? useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<!-- 项目上线后使用的数据库-->
<environment id="online">
<transactionManager type="JDBC"/>
<!--配置数据源: 创建Connection对象-->
<dataSource type="POOLED">
<!-- driver: 驱动的内容-->
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- url: 连接数据库的URL 注意:html 标签实体-->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis? useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
5.4 使用数据库属性配置文件–!
需要把数据库的配置信息放到一个单独的文件中,独立管理。这个文件的拓展名是properties。在这个文件中,使用自定义的key=value的格式表示数据。
使用步骤:
- 在resources目录中。创建xxx.properties
- 在文件中,使用 key = value 的格式定义数据
例如 :jdbc.url=jdbc:mysql://localhost:3306/mybatis
- 在mybatis主配置文件,使用properties标签引用外部的属性配置文件
- 在使用值的位置,使用 ${} 获取 key 对应的 value(等号右侧的值)
5.5 mapper标签–!
使用mapper指定其他mapper文件的位置
mapper标签格式有两种,
- 第一种方式:resource=”mapper文件路径“
- 优点:文件清晰,加载的文件是明确的。文件位置灵活。
- 缺点:文件比较多时,代码量会比较大,股那里难度大。
<mapper>
<mapper resource="**/**/**" />
</mapper>
- 第二种方式:使用, name:包名,mapper文件所在的包名。
- 特点:把这个包中所有mapper文件,一次加载。
- 使用要求:
- mapper文件和dao接口在同一目录。
- mapper文件到dao接口名称完全相同。
<mapper>
<package name="**.**.**" />
</mapper>
第六章 拓展-PageHelper
PageHelper做数据分页。
在你的select语句后面加入分页的sql内容。如果你使用mysql数据库,它就是在 select * from student 后面加入 limit 语句。
使用步骤:
-
加入依赖(PageHelper依赖)
<dependency> <groupId>com.github,pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency>
-
在mybatis主配置文件中加入plugin声明
在<environments>之前加入plugin <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"/> </plugins>
-
在select语句之前,调用PageHelper.startPage(页码,每页大小)。
对比:
没有使用PageHelper:
select * from student
使用PageHelper:
SELECT count(*) FROM student
select * from student LIMIT ?