'mybatis框架原理
持久层框架 对JDBC的封装
原生态JDBC程序问题
mybatis开发dao
原始dao开发方法 程序需要编写dao接口和dao实现类(掌握)
mybatis的mapper接口 代理开发方法 (掌握)
---------------------------------------------------------
mybatis配置文件 SqlMapConfig.xml
mybatis核心
mybatis输入映射
mybatis输出映射
mybatis的动态sql
高级结果集映射 (一对一,一对多,多对多)
mybatis延迟加载
mybatis查询缓存(一级缓存,二级缓存)
mybatis逆向工程
----------------------------------------------------
原生jdbc编程的问题总结
1 加载数据库驱动
fornName.class("com.jdbc.mysql.Driver");
2 获取连接
conn = DriverManager.getConnection("")
------------------------------------------------
1:数据库连接,使用时就创建,不使用就立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
解决办法:使用数据库连接池管理数据库连接
2:将sql语句硬编码到java代码中,如果sql语句修改,则需要修改代码重新编译,不利于系统维护
设想:将sql语句配置在xml配置文件当中,即使sql变化,不需要对java代码进行重新编译。
3:向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
4:从resultset中遍历结果集数据时存在硬编码,将获取表的字段进行硬编码,不利于系统维护
设想:将查询的结果集,自动映射成java对象。
-------------------------------------------------------
mybatis框架原理
mybatis是一个持久层框架,是apache下的顶级项目。
mybatis让程序员主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)
mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
SqlMapConfig.xml 是mybatis的全局配置文件
配置了数据源,事务等mybatis运行环境
配置映射(配置sql语句)
mapper.xml (映射文件)
SqlSessionFactoty(会话工厂) 创建SqlSession
SqlSession会话 是一个接口
增删改查
Executor(执行器)
作用:SqlSession内部通过执行器操作数据库
底层封装对象
mapped statement
--------------------------------------------------
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">
<!-- 注意:每个标签必须按顺序写,不然蛋疼的DTD会提示错误:The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,plugins?,environments?,mappers?)". -->
<configuration>
<!-- 和spring整合后enviroment将废弃 -->
<environments default="development">
<environment id="development">
<!-- jdbc事务 -->
<transactionManager type="JDBC"/>
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="huang110"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlmap/user.xml"/>
</mappers>
</configuration>
-------------------------------------------------
在映射文件中配置sql语句
user.xml ibatis前身
usermapper.xml
resultType 指的是单条记录所映射的java对象类型
selectList
#{}
'%${value}%'拼接字符串
可能会引起sql注入 修改拼接的字符串 如果是简单类型 ${}只能是value
selectOne取出一条记录
selectList取出多条记录
如果使用selectList查询多条数据,则不能使用selectOne
resultType paparameterType
'''
------------------------------------------------------------------------------
'添加用户
在User.xml配置sql(statement)
<?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">
<mapper namespace="test">
<select id="finduserById" parameterType="int" resultType="com.mybatis.user">
select * from user where id = #{value}<!-- 标示一个占位符 -->
</select>
<insert id="insertUser" parameterType="com.mybatis.user">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(name,age) value(#{name},#{age})
</insert>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{value};
</delete>
<!-- 更新 -->
<update id="updateUser" parameterType="com.mybatis.user">
update user set name=#{name} ,age=#{age} where id=#{id}
</update>
</mapper>
<insert id="insertUser" parameterType="com.mybatis.user">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(name,age) value(#{name},#{age})
</insert>
只适用自增id
---------------------------------------------------------------------
select UUID(); varchar(35)
先通过uuid查询到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
select UUID()
</selectKey>
insert into user(id,name,age) value(#{id},#{name},#{age})
------------------------------------------------------------------------
删除用户
更新用户
#{}标示一个占位符,可以是简单类型,pojo,hashmap
如果接收简单类型#{}中可以写成value或其他值
${}标示一个占位符,可以是简单类型,pojo,hashmap
如果接收简单类型#{}中只能写成value
'
--------------------------------------
OGNL
--------------------------------------
'
parameterType resultType
---------------------------------------------------------------
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Hibernate 和 Mybatis本质区别 和应用场景
hibernate入门门槛比较高
标准的ORM框架,不需要程序员编写SQL语句
不利于SQL语句优化,修改
----------------------------------------------------------------
Mybatis:专注SQL本身,方便SQL优化,修改。mybatis是一个不完全的ORM框架
虽然程序员自己写sql,mybatis也可以实现映射(输入映射,输出映射);
Hibernate 适用需求变化不多的中小型项目 比如:后台管理系统,erp,orm,oa
mybatis适用需求变化较多的项目 比如:互联网项目
企业进行技术选型,以低成本,高回报作为技术选型的原则
适用项目本身的技术,根据项目组的技术力量进行选择。
'-------------------------------------------------------------
'mybatis 开发Dao的方法
(工厂一旦创建,使用一个实例)
通过SqlSessionFactory创建SqlSession使用单例模式管理sqlSessionFactory
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory
sqlSession面向用户(程序员)的接口
sqlSession是线程不安全的,在sqlSession实现类中除了有接口中的方法还有数据域属性
sqlsession最佳应用场合在方法体内定义成局部变量。
---------------------------------------------------------------
原始DAO开发方法
程序员需要写dao接口和dao实现
需要向dao实现类注入sessionfactory
->原始dao开发问题
代码重复较多。存在大量的模版方法
设想将这些代码提取出来
调用sqlsession方法时将statement id硬编码了
传入的变量由于sqlsession方法使用泛型,如果传入变量错了
编译期间不报错。
---------------------------------------------------------------
mapper代理方法
程序员需要写mapper接口
程序还需要编写mapper.xml
mybatis可以自动生成mapper接口实现类代理对象
开发规范;
1 在mapper.xml中namespace等于mapper接口地址
2 mapper接口中方法名和mapper.xml中statement的id一致
3 mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
4 mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致
mapper接口方法参数只能有一个,系统是否不利于扩展维护。
即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层方法参数
'
如果返回类型为一个pojo对象 内部调用 selectOne()
---------------------------------------------------------------------------
SqlMapConfig Mybatis全局配置文件
properties属性
需求:
将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig中加载db.properties属性值
这样sqlmapconfig就不需要对数据库连接参数硬编码。
1 在properties元素体内定义的属性首先被读取
2 然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性。
3 最后读取parameterType传递的属性,它会覆盖已读取的同名属性
---------------------------------------------------
建议不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
定义的属性名要有一定的特殊性
settings全局配置参数
mybatis框架在运行时可以调整一些参数
全局参数会影响mybatis的运行行为
---------------------------------------------------
typeAliases 别名 (重点)
需求 在mapper.xml中定义很多的statement ,statemet需要parameterType指定输入参数的类型
如果在指定类型时输入类型全路径,不方便进行开发。可以针对parameterType定义一些别名
<typeAliases >
<!-- <typeAlias type="com.mapper.user" alias="user"/>-->
<!-- 批量别名定义 -->
<package name="com.mapper"/> 自动定义别名,别名就是类名(不区分大小写)
</typeAliases>
------------------------------------------------------------------------------
typeHandlers (类型处理器)
mybatis通过typeHandlers完成jdbc类型和java类型的转换
通常情况下
-----------------------------------------------------------------------------------
objectFactory
plugins
------------------------------------------------------------------------------
mappers(映射配置)
<mappers>
<mapper resource=""/>单个映射文件加载
<mapper class=""/>
</mappers>
-------------------------------------------------------------------------------
通过mapper接口加载
需要将mapper接口类名和mapper.xml映射文件名称保持一致且在一个目录中
使用mapper代理方式
<mapper class="" />
<!--批量加载-->
指定mapper接口的包名 自动扫描包下边所有mapper
<package name="com.mybatis"/>
-------------------------------------------------------------------------------
pojo(简单的java对象)包装类型 输入映射
需求--
用户信息的综合查询需要传入查询条件(可能包括用户信息,其他信息,比如商品,订单等)
针对上边需求,建议使用自定义的包装类型的pojo
-----------------------------------------------------------------------------------------
复杂查询 pojo对象
2018/05/19
输出映射
resultType
如果查询出来的列名和pojo是属性名不一致,通过定义一个resultMap 对列名和pojo属性名
resultMap
type resultMap最终映射的java对象类型,可以使用别名 类似 <select>中的resultType
<resultMap type="user" id="usemappermap">
<id column="id_" property="id"/> column查询出来的列名 property指定的pojo类型中的属性名
<result column="usename_" property=" "/>
</resultMap>
<select id=" " parameterType=" " resultMap="usemappermap" >
</select>
---------------------------------------------------------------------------------------------
动态sql mybatis 核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接,组装。
<where>
<if test = " name!=null" >
and name=#{name}
</if>
<if test=" ">
</if>
</where>
自动去掉第一个and
------------------------------------------------------------------------------------------
片段 将上边实现的动态sql判断代码块
经验: 是基于单表来定义sql片段,这样的话这个sql片段的可重用性高
在sql片段中不要包括where
<sql id="">
<if test="">
</if>
</sql>
----------------------------------------
<where>
<include refid=" " ></include>
</where>
-----------------------------------------------
foreach
向sql传递数组或list,nybatis使用foreach解析
collection:指定输入对象中集合属性
item:每个遍历生成对象中
open:开始遍历时拼接串
实现下面的sql拼接
AND (id=1 or id=2 or id=3)
----------------------------------------------------------------------------------------
<foreach collection="ids" item="id" open="AND ( " close=" )" separator=" OR " />
----------------------------------------------------------------------------------------
2018/05/20
高级映射 查询缓存 和spring整合
课程复习:
mybatatis是什么?
持久层框架 Mybatis是一个不完全的ORM框架。sql语句需要程序员自己去编写,但是mybatis也
有映射(输入参数映射,输出结果映射)
mybatis入门门槛不高,学习成本低,让程序员把精力放在sql语句上,对sql语句优化非常方便,适用于需求变化较多项目,
比如互联网项目。
实现一对一查询,一对多,多对多查询
一级缓存 二级缓存
mybatis和spring整合(掌握)
逆向工程
------------------------------------------------------
订单查询商品模型
resultType 实现一对一
resultMap
association用于映射关联查询单个对象的信息
property要关联查询的用户信息映射到orders中的哪个属性
<association property="user" javaType="cn.mapper.User">
<id column=" " property=" "/>
<result column=" " property=" "/>
</association>
resultMap可以实现延迟加载
order
{
User user;
}
-------------------------------------------------------------
collection 对关联查询到多条记录映射到集合对象中
property将关联查询到多条记录映射到cn.dss.**哪个属性上
ofType:指定映射集合类型的类型
<collection property="" ofType="">
</collection>
extends
-------------------------------------------------------------
多对多
需求: 查询用户及用户购买商品信息
主表: 用户表
关联表:由于用户和商品没有直接关联,通过订单,和订单明细进行关联。
在user类中添加订单列表属性 List<Orders>orderdetials,将用户创建的订单映射到orderslist
在Orders中添加订单明细列表属性List<OrderDetail>orderdetials将订单的明细映射到orderdetials
在OrderDetail中添加items属性,将订单明细所对应的商品映射到items--
<association></association>
<colletcion></collection>
resultType 属性名和列名一致才能完成映射
resultMap
-------------------------------------------------------------------
延迟加载
什么是延迟加载?
resultMap可以实现高级映射 association collection
具备延迟加载的功能。
按需查询就是延迟加载 大大提高数据库性能
select:指定延迟加载需要执行的statement的id()
column关联查询的列
<association property="" javaType="" select="" column="">
</association>
--------------------------------------------------------------
mybatis默认没有开启延迟加载
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
----------------------------------------------------------------
查询缓存
用于减轻数据库压力,提高数据库性能
"一级缓存"
sqlsession
在操作数据时需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据
不同的sqlsession之间的缓存数据区域(HashMap)是互相不影响的。
"二级缓存"
mapper(namespace)
二级缓存是mapper级别的缓存,多个sqlsession去操作同一个Mapper的sql语句。多个sqlsession去
操作数据库得到数据会存在二级缓存区域,二级缓存是跨sqlsession的。
commit 清空缓存
避免脏读
-------------------------------------------------------------------
一级缓存的实际应用、
mybatis默认支持一级缓存,不需要在配置文件里面去配
正式开发是将mybatis和spring进行整合开发,事务控制在service中。一个service方法中包括很多mapper方法调用
-----------------------------------------------------------------------
二级缓存
首先开启mybatis的二级缓存
二级缓存与一级缓存的区别
多个sqlsession共享同一个sqlsession可以共享一个namespace的二级缓存区域
二级缓存按namespace分的
每个namespace都有一个二级缓存
如果中间存在 去执行相同mapper下sql执行commit提交
二级缓存会被清空。
是mapper范围级别的
除了在sqlMapConfig.xml开启
还得在mapper设置
<setting name="cacheEnabled" value="true" />
在mapper开启二级缓存
<mapper namespace="" >
<cache />开启二级缓存
</mapper>
mapper.xml下的sql执行会存到缓存中
pojo对象 实现序列化接口 为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质
多种多样
sqlsession不关闭 sqlsession中的数据才能写到二级缓存中
--------------------------------------------------------------
mybatis整合ehcache
ehcache是一个分布式缓存框架
为了提高系统并发,性能,一般对系统进行分布式部署(集群部署方式)
不使用分布缓存缓存数据在各自服务器单独存储
登录记录
对缓存数据进行集中管理,使用分布式缓存框架,对数据集中管理
redis,memcached.ehcache
mybatis无法实现分布式缓存,需要和其他分布式缓存框架进行整合
整合方法
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑实现cache接口开发即可
mybatis和ehcache整合,mybatis和ehcache整合包提供了一个cache接口的实现类
加入ehcachejar包
<cache type="实现了cache接口的类" />
org.mybatis.caches.ehcache.EhcacheCache
添加ehcache配置文件
实际情况下二级缓存用的比较多
访问多 对实时性要求不高
查询特别耗时的情况下
flushInterval刷新频率 清空缓存
'二级缓存的局限性:
mybatis二级缓存对细粒度的数据级别缓存实现不好,比如如下需求:对商品信息进
行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如
果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新
其他商品信息,因为mybatis的二级缓存区域mapper为单位划分,当一个商品信息变化会将所有
商品信息的缓存数据全部清空。解决此类问题需要要在业务层根据需求对数据有针对性缓存。
-----------------------------------------------------------------------------------
spring和mybatis整合
需要spring通过单例方式管理sqlsessionFactory
spring和mybatis整合生成代理对象,使用sqlsessionfactory创建sqlsession(spring和mybatis整合自动完成)
持久层的mapper都需要由spring进行管理
接近实际开发工程目录
-----------------------------------------------
原始DAO开发方法(和spring整合后)
创建mapper.xml
如果扫描多个包,每个包中间使用半角分隔符分隔
-------------------------------------------------------------
逆向工程
mybatis需要程序自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码
(mapper.java,mapper.xml,po)
企业实际开发中,常用的逆向工程方式
由数据库的表生成java代码
运行逆向工程
建议使用java程序方式,不依赖运行环境
'mybatis框架原理
持久层框架 对JDBC的封装
原生态JDBC程序问题
mybatis开发dao
原始dao开发方法 程序需要编写dao接口和dao实现类(掌握)
mybatis的mapper接口 代理开发方法 (掌握)
---------------------------------------------------------
mybatis配置文件 SqlMapConfig.xml
mybatis核心
mybatis输入映射
mybatis输出映射
mybatis的动态sql
高级结果集映射 (一对一,一对多,多对多)
mybatis延迟加载
mybatis查询缓存(一级缓存,二级缓存)
mybatis逆向工程
----------------------------------------------------
原生jdbc编程的问题总结
1 加载数据库驱动
fornName.class("com.jdbc.mysql.Driver");
2 获取连接
conn = DriverManager.getConnection("")
------------------------------------------------
1:数据库连接,使用时就创建,不使用就立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
解决办法:使用数据库连接池管理数据库连接
2:将sql语句硬编码到java代码中,如果sql语句修改,则需要修改代码重新编译,不利于系统维护
设想:将sql语句配置在xml配置文件当中,即使sql变化,不需要对java代码进行重新编译。
3:向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
4:从resultset中遍历结果集数据时存在硬编码,将获取表的字段进行硬编码,不利于系统维护
设想:将查询的结果集,自动映射成java对象。
-------------------------------------------------------
mybatis框架原理
mybatis是一个持久层框架,是apache下的顶级项目。
mybatis让程序员主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)
mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
SqlMapConfig.xml 是mybatis的全局配置文件
配置了数据源,事务等mybatis运行环境
配置映射(配置sql语句)
mapper.xml (映射文件)
SqlSessionFactoty(会话工厂) 创建SqlSession
SqlSession会话 是一个接口
增删改查
Executor(执行器)
作用:SqlSession内部通过执行器操作数据库
底层封装对象
mapped statement
--------------------------------------------------
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">
<!-- 注意:每个标签必须按顺序写,不然蛋疼的DTD会提示错误:The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,plugins?,environments?,mappers?)". -->
<configuration>
<!-- 和spring整合后enviroment将废弃 -->
<environments default="development">
<environment id="development">
<!-- jdbc事务 -->
<transactionManager type="JDBC"/>
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="huang110"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlmap/user.xml"/>
</mappers>
</configuration>
-------------------------------------------------
在映射文件中配置sql语句
user.xml ibatis前身
usermapper.xml
resultType 指的是单条记录所映射的java对象类型
selectList
#{}
'%${value}%'拼接字符串
可能会引起sql注入 修改拼接的字符串 如果是简单类型 ${}只能是value
selectOne取出一条记录
selectList取出多条记录
如果使用selectList查询多条数据,则不能使用selectOne
resultType paparameterType
'''
------------------------------------------------------------------------------
'添加用户
在User.xml配置sql(statement)
<?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">
<mapper namespace="test">
<select id="finduserById" parameterType="int" resultType="com.mybatis.user">
select * from user where id = #{value}<!-- 标示一个占位符 -->
</select>
<insert id="insertUser" parameterType="com.mybatis.user">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(name,age) value(#{name},#{age})
</insert>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{value};
</delete>
<!-- 更新 -->
<update id="updateUser" parameterType="com.mybatis.user">
update user set name=#{name} ,age=#{age} where id=#{id}
</update>
</mapper>
<insert id="insertUser" parameterType="com.mybatis.user">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(name,age) value(#{name},#{age})
</insert>
只适用自增id
---------------------------------------------------------------------
select UUID(); varchar(35)
先通过uuid查询到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
select UUID()
</selectKey>
insert into user(id,name,age) value(#{id},#{name},#{age})
------------------------------------------------------------------------
删除用户
更新用户
#{}标示一个占位符,可以是简单类型,pojo,hashmap
如果接收简单类型#{}中可以写成value或其他值
${}标示一个占位符,可以是简单类型,pojo,hashmap
如果接收简单类型#{}中只能写成value
'
--------------------------------------
OGNL
--------------------------------------
'
parameterType resultType
---------------------------------------------------------------
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Hibernate 和 Mybatis本质区别 和应用场景
hibernate入门门槛比较高
标准的ORM框架,不需要程序员编写SQL语句
不利于SQL语句优化,修改
----------------------------------------------------------------
Mybatis:专注SQL本身,方便SQL优化,修改。mybatis是一个不完全的ORM框架
虽然程序员自己写sql,mybatis也可以实现映射(输入映射,输出映射);
Hibernate 适用需求变化不多的中小型项目 比如:后台管理系统,erp,orm,oa
mybatis适用需求变化较多的项目 比如:互联网项目
企业进行技术选型,以低成本,高回报作为技术选型的原则
适用项目本身的技术,根据项目组的技术力量进行选择。
'-------------------------------------------------------------
'mybatis 开发Dao的方法
(工厂一旦创建,使用一个实例)
通过SqlSessionFactory创建SqlSession使用单例模式管理sqlSessionFactory
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory
sqlSession面向用户(程序员)的接口
sqlSession是线程不安全的,在sqlSession实现类中除了有接口中的方法还有数据域属性
sqlsession最佳应用场合在方法体内定义成局部变量。
---------------------------------------------------------------
原始DAO开发方法
程序员需要写dao接口和dao实现
需要向dao实现类注入sessionfactory
->原始dao开发问题
代码重复较多。存在大量的模版方法
设想将这些代码提取出来
调用sqlsession方法时将statement id硬编码了
传入的变量由于sqlsession方法使用泛型,如果传入变量错了
编译期间不报错。
---------------------------------------------------------------
mapper代理方法
程序员需要写mapper接口
程序还需要编写mapper.xml
mybatis可以自动生成mapper接口实现类代理对象
开发规范;
1 在mapper.xml中namespace等于mapper接口地址
2 mapper接口中方法名和mapper.xml中statement的id一致
3 mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
4 mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致
mapper接口方法参数只能有一个,系统是否不利于扩展维护。
即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层方法参数
'
如果返回类型为一个pojo对象 内部调用 selectOne()
---------------------------------------------------------------------------
SqlMapConfig Mybatis全局配置文件
properties属性
需求:
将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig中加载db.properties属性值
这样sqlmapconfig就不需要对数据库连接参数硬编码。
1 在properties元素体内定义的属性首先被读取
2 然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性。
3 最后读取parameterType传递的属性,它会覆盖已读取的同名属性
---------------------------------------------------
建议不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
定义的属性名要有一定的特殊性
settings全局配置参数
mybatis框架在运行时可以调整一些参数
全局参数会影响mybatis的运行行为
---------------------------------------------------
typeAliases 别名 (重点)
需求 在mapper.xml中定义很多的statement ,statemet需要parameterType指定输入参数的类型
如果在指定类型时输入类型全路径,不方便进行开发。可以针对parameterType定义一些别名
<typeAliases >
<!-- <typeAlias type="com.mapper.user" alias="user"/>-->
<!-- 批量别名定义 -->
<package name="com.mapper"/> 自动定义别名,别名就是类名(不区分大小写)
</typeAliases>
------------------------------------------------------------------------------
typeHandlers (类型处理器)
mybatis通过typeHandlers完成jdbc类型和java类型的转换
通常情况下
-----------------------------------------------------------------------------------
objectFactory
plugins
------------------------------------------------------------------------------
mappers(映射配置)
<mappers>
<mapper resource=""/>单个映射文件加载
<mapper class=""/>
</mappers>
-------------------------------------------------------------------------------
通过mapper接口加载
需要将mapper接口类名和mapper.xml映射文件名称保持一致且在一个目录中
使用mapper代理方式
<mapper class="" />
<!--批量加载-->
指定mapper接口的包名 自动扫描包下边所有mapper
<package name="com.mybatis"/>
-------------------------------------------------------------------------------
pojo(简单的java对象)包装类型 输入映射
需求--
用户信息的综合查询需要传入查询条件(可能包括用户信息,其他信息,比如商品,订单等)
针对上边需求,建议使用自定义的包装类型的pojo
-----------------------------------------------------------------------------------------
复杂查询 pojo对象
2018/05/19
输出映射
resultType
如果查询出来的列名和pojo是属性名不一致,通过定义一个resultMap 对列名和pojo属性名
resultMap
type resultMap最终映射的java对象类型,可以使用别名 类似 <select>中的resultType
<resultMap type="user" id="usemappermap">
<id column="id_" property="id"/> column查询出来的列名 property指定的pojo类型中的属性名
<result column="usename_" property=" "/>
</resultMap>
<select id=" " parameterType=" " resultMap="usemappermap" >
</select>
---------------------------------------------------------------------------------------------
动态sql mybatis 核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接,组装。
<where>
<if test = " name!=null" >
and name=#{name}
</if>
<if test=" ">
</if>
</where>
自动去掉第一个and
------------------------------------------------------------------------------------------
片段 将上边实现的动态sql判断代码块
经验: 是基于单表来定义sql片段,这样的话这个sql片段的可重用性高
在sql片段中不要包括where
<sql id="">
<if test="">
</if>
</sql>
----------------------------------------
<where>
<include refid=" " ></include>
</where>
-----------------------------------------------
foreach
向sql传递数组或list,nybatis使用foreach解析
collection:指定输入对象中集合属性
item:每个遍历生成对象中
open:开始遍历时拼接串
实现下面的sql拼接
AND (id=1 or id=2 or id=3)
----------------------------------------------------------------------------------------
<foreach collection="ids" item="id" open="AND ( " close=" )" separator=" OR " />
----------------------------------------------------------------------------------------
2018/05/20
高级映射 查询缓存 和spring整合
课程复习:
mybatatis是什么?
持久层框架 Mybatis是一个不完全的ORM框架。sql语句需要程序员自己去编写,但是mybatis也
有映射(输入参数映射,输出结果映射)
mybatis入门门槛不高,学习成本低,让程序员把精力放在sql语句上,对sql语句优化非常方便,适用于需求变化较多项目,
比如互联网项目。
实现一对一查询,一对多,多对多查询
一级缓存 二级缓存
mybatis和spring整合(掌握)
逆向工程
------------------------------------------------------
订单查询商品模型
resultType 实现一对一
resultMap
association用于映射关联查询单个对象的信息
property要关联查询的用户信息映射到orders中的哪个属性
<association property="user" javaType="cn.mapper.User">
<id column=" " property=" "/>
<result column=" " property=" "/>
</association>
resultMap可以实现延迟加载
order
{
User user;
}
-------------------------------------------------------------
collection 对关联查询到多条记录映射到集合对象中
property将关联查询到多条记录映射到cn.dss.**哪个属性上
ofType:指定映射集合类型的类型
<collection property="" ofType="">
</collection>
extends
-------------------------------------------------------------
多对多
需求: 查询用户及用户购买商品信息
主表: 用户表
关联表:由于用户和商品没有直接关联,通过订单,和订单明细进行关联。
在user类中添加订单列表属性 List<Orders>orderdetials,将用户创建的订单映射到orderslist
在Orders中添加订单明细列表属性List<OrderDetail>orderdetials将订单的明细映射到orderdetials
在OrderDetail中添加items属性,将订单明细所对应的商品映射到items--
<association></association>
<colletcion></collection>
resultType 属性名和列名一致才能完成映射
resultMap
-------------------------------------------------------------------
延迟加载
什么是延迟加载?
resultMap可以实现高级映射 association collection
具备延迟加载的功能。
按需查询就是延迟加载 大大提高数据库性能
select:指定延迟加载需要执行的statement的id()
column关联查询的列
<association property="" javaType="" select="" column="">
</association>
--------------------------------------------------------------
mybatis默认没有开启延迟加载
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
----------------------------------------------------------------
查询缓存
用于减轻数据库压力,提高数据库性能
"一级缓存"
sqlsession
在操作数据时需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据
不同的sqlsession之间的缓存数据区域(HashMap)是互相不影响的。
"二级缓存"
mapper(namespace)
二级缓存是mapper级别的缓存,多个sqlsession去操作同一个Mapper的sql语句。多个sqlsession去
操作数据库得到数据会存在二级缓存区域,二级缓存是跨sqlsession的。
commit 清空缓存
避免脏读
-------------------------------------------------------------------
一级缓存的实际应用、
mybatis默认支持一级缓存,不需要在配置文件里面去配
正式开发是将mybatis和spring进行整合开发,事务控制在service中。一个service方法中包括很多mapper方法调用
-----------------------------------------------------------------------
二级缓存
首先开启mybatis的二级缓存
二级缓存与一级缓存的区别
多个sqlsession共享同一个sqlsession可以共享一个namespace的二级缓存区域
二级缓存按namespace分的
每个namespace都有一个二级缓存
如果中间存在 去执行相同mapper下sql执行commit提交
二级缓存会被清空。
是mapper范围级别的
除了在sqlMapConfig.xml开启
还得在mapper设置
<setting name="cacheEnabled" value="true" />
在mapper开启二级缓存
<mapper namespace="" >
<cache />开启二级缓存
</mapper>
mapper.xml下的sql执行会存到缓存中
pojo对象 实现序列化接口 为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质
多种多样
sqlsession不关闭 sqlsession中的数据才能写到二级缓存中
--------------------------------------------------------------
mybatis整合ehcache
ehcache是一个分布式缓存框架
为了提高系统并发,性能,一般对系统进行分布式部署(集群部署方式)
不使用分布缓存缓存数据在各自服务器单独存储
登录记录
对缓存数据进行集中管理,使用分布式缓存框架,对数据集中管理
redis,memcached.ehcache
mybatis无法实现分布式缓存,需要和其他分布式缓存框架进行整合
整合方法
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑实现cache接口开发即可
mybatis和ehcache整合,mybatis和ehcache整合包提供了一个cache接口的实现类
加入ehcachejar包
<cache type="实现了cache接口的类" />
org.mybatis.caches.ehcache.EhcacheCache
添加ehcache配置文件
实际情况下二级缓存用的比较多
访问多 对实时性要求不高
查询特别耗时的情况下
flushInterval刷新频率 清空缓存
'二级缓存的局限性:
mybatis二级缓存对细粒度的数据级别缓存实现不好,比如如下需求:对商品信息进
行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如
果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新
其他商品信息,因为mybatis的二级缓存区域mapper为单位划分,当一个商品信息变化会将所有
商品信息的缓存数据全部清空。解决此类问题需要要在业务层根据需求对数据有针对性缓存。
-----------------------------------------------------------------------------------
spring和mybatis整合
需要spring通过单例方式管理sqlsessionFactory
spring和mybatis整合生成代理对象,使用sqlsessionfactory创建sqlsession(spring和mybatis整合自动完成)
持久层的mapper都需要由spring进行管理
接近实际开发工程目录
-----------------------------------------------
原始DAO开发方法(和spring整合后)
创建mapper.xml
如果扫描多个包,每个包中间使用半角分隔符分隔
-------------------------------------------------------------
逆向工程
mybatis需要程序自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码
(mapper.java,mapper.xml,po)
企业实际开发中,常用的逆向工程方式
由数据库的表生成java代码
运行逆向工程
建议使用java程序方式,不依赖运行环境