框架技术
1.框架技术
01.是一个应用程序的半成品
02.提供可重用的公共结构
03.按一定规则组织的一组组件
2.分析优势
01.不用再考虑公共问题
02.专心的业务实现上
03.结构统一,易于学习、维护
04.新手也可写出好程序
3.主流框架简介
01.Struts2(Web层框架)
MVC设计模式的实现
拦截器
可变和可重用的标签
02.HIBERNATE(DAO层框架)
ORM(对象关系映射),简化数据库操作
DAO层
03. Spring
依赖注入容器(IOC)/AOP(面向切面编程)实现
声明式事务
简化Java EE应用
粘合剂,将大家组装到一起
Spring MVC
结构最清晰的MVC Model2实现
高度可配置,支持多种视图技术
定制化开发
04.MyBatis
半自动化的ORM实现
DAO层
小巧灵活、简单易学
4.持久化与ORM
01.持久化是程序数据在瞬时状态和持久化状态间转换的过程
瞬时状态
在临时内存中存储,进行数据交互
持久状态
把瞬时状态的数据长期的保存在硬盘中
02.ORM(对象关系映射)
ORM(Object Relational Mapping)
编写程序的时候,以面向对象的方式处理数据
保存数据的时候,却以关系型数据库的方式存储
ORM解决方案包含下面四个部分
在持久化对象上执行基本的增、删、改、查操作
对持久化对象提供一种查询语言或者API
对象关系映射工具
提供与事务对象交互、执行检查、延迟加载以及其他优化功能
MyBatis环境搭建
1.MyBatis简介
01.MyBatis前身是iBatis,本身是Apache的一个开源的项目
02.官方网站
http://mybatis.ory
03.ORM框架
04.实体类和SQL语句之间建立映射关系
05.特点
基于SQL语法,简单易学
能了解底层封装过程
SQL语句封装在配置文件中,便于统一管理与维护,降低程序的耦合度
方便程序代码调试
2.搭建Mybatis开发环境
01.下载MyBatis-3.2.2.jar包并导入工程
02.编写MyBatis核心配置文件(configuration.xml)
03.创建实体类-POPJ
04.DAO层-SQL映射文件(mapper.xml)
05.创建测试类
读取全局配置文件mybatis-config.xml
创建SqlSessionFactory对象,读取配置文件
创建SqlSession对象
调用mapper文件进行数据操作
3.MyBatis框架优点缺点
01.优点
与JDBC相比,减少了50%以上的代码量
最简单的持久化框架、小巧并简单易学
SQL代码从程序代码中彻底分离,可重用
提供XML标签,支持编写动态SQL
提供映射标签,支持对象与数据库的ORM字段关系映射
02.缺点
SQL语句编写工作量大,对开发人员有一定要求
数据库移植性差
*MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案,适合于性能要求较高或者需求多变的互联网项目
Maven
1.Maven简介
01.maven是一个项目构建和管理的工具,提供了帮助管理构建、文档、报告、依赖、发布、分发的方法。 可以方便的编译代码,进行依赖关系,管理二进制库等等
02.maven的好处在于可以将项目过程规范化、自动化、高效化以及强大的可扩展性
03.利用maven自身及其插件还可以获得代码检查报告、单元测试覆盖率。实现持续集成等等。
2.Maven仓库
01.Maven仓库本质上存储了jar包和原数据信息,通过原信息能够准确定位到jar包,从而能够获取和修改
02.Maven的三种类型仓库
001.本地仓库
本地仓库默认在用户目录下,包含了下载的所有依赖
002.中央仓库
中央仓库由Maven自己提供的,本地仓库中的没有依赖默认都会去中央仓库查找,下载后会放到本地仓库
003.远程仓库
远程仓库是远程服务器上可访问的仓库,本质类似于中央仓库(只不过中央仓库是权威罢了,而且你不能乱动)。远程仓库可以本地网络中或者互联网上,一般团队内部会设置一个内部的远程仓库,这样可以解决安全共享,网络代理等问题
注意:Maven首先会从本地仓库,然后是中央仓库,最后结果pom文件中配置了远程仓库,会到远程仓库中查找依赖
3.maven目录
src/main/java --> 存放Java代码
src/main/resource --> 存放Java代码中的依赖,例如小配置文件(.xml)
src/test/java
src/test/resource
4.session.getMapper()方法
01.使用强制类型的方式,直接点出业务方法
02.返回值类型为借口定义方法的类型
03.方法用到了,动态代理--->里式替换。
5.别名
由于在小配置中,resultType(返回值类型),parameterType(参数类型)。
如果在开发中不想写全名称,想使用别名
01.方法一
<typeAliases>
<typeAlias type="类全名称" alias="别名"></typeAlias>
</typeAliases>
*注意
01.1
在大配置中配置
01.2
在业务量大的时候,配置会很烦琐
02.方法二
<typeAliases>
<package name="类的全包名"/>
</typeAliases>
*注意
02.1
在大配置中配置
02.2
在业务量大的时,配置简单
6.resultType和resultMap的区别
01.resultType
指向类的名称
一般为返回值类型
02.resultMap
<select id="myGetUserById" resultMap="myUser">
SELECT * FROM t_user WHERE id = #{id}
</select>
<resultMap id="myUser" type="com.yunqing.mybatis.bean.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</resultMap>
说明
column:数据库列名
property:对应的javabean属性
7.SQL片段(小配置文件中SQL语句替代“*”号)
01.声明sql标签
<sql id="aaa">
sql列名
</sql>
02.使用include标签指向sql标签
<select id="isQuery">
select <include refid="aaa"></include> form book
</select>
8.模糊查询
*在小配置中实现模糊查询得方式
01.使用concat连接
select * form student where stuName like concat('%',#{stuName},'%')
*可以防止SQL的注入
02.使用'${value}'
select * form student where stuName like '${value}'
*不防止SQL注入
03.使用'%'#{value}'%'
select * form student where stuName like '%'#{value}'%'
*可以防止SQL注入
9.添加完成后获取ID
<insert id="insertStudent">
insert into student(stuName,stuAge) values(#{stuname},#{stuage)
<selectKey resultType="int" keyProperty="stuNo">
select @@identity
</selectKey>
</insert>
*通过在小配合文件中insert标签中添加selectKey标签获取
10.多条件查询
10.1
Map集合的方式传递参数
01.在接口中定义的方法入参类型为Map集合
02.小配置文中指定参数为key值,通过实现类的Map集合获取
10.2
通过站位传递参数
01.在接口中定义的方法根据需要入参
02.小配置文中直接按入参的顺序进行站位
11.智能标签
11.1
if
01.小配置中(示例)
<select id="findByIf" resultType="Book">
select * from Book
<where>
<if test="bookName!=null">
and bookName like '%' #{bookName} '%'
</if>
</where>
</select>
*if标签中test属性就是条件语句,成则进入标签体。
if标签可有多个。and必须存在,不必担心和where拼接
11.2
choose
01.示例
<select id="findByChoose" resultType="Book">
select * from book
<where>
<choose>
<when test="bookName!=null">
and BookName like '%' #{bookName} '%'
</when>
<when test="bookName!=null">
and BookDate like '%' #{bookDate} '%'
</when>
<otherwise>1=1</otherwise>
</choose>
</where>
</select>
*类似于switch,只会走一个分支
没有符合条件的走otherwise标签
11.3
foreach
01.foreach array示例
<select id="findByForeachArray" resultType="Book">
select * from book
<where>
bookId in
<foreach clooection="array" open="(" close=")" separator="," item="myid">
#{myid}
</foreach>
</where>
</select>
*
以上代码可以实现
select * from book bookId in(3,4)
小括号中的内容主要根据实现类中给方法中赋值的数组而定
接口方法的入参类型为int类型数组
foreach标签属性
clooection
循环的类型
open
开头
close
结尾
separator
每次循环的分割
item
值
02.foreach list示例
<select id="findByForeachArray" resultType="Book">
select * from book
<where>
bookId in
<foreach clooection="list" open="(" close=")" separator="," item="myid">
#{myid}
</foreach>
</where>
</select>
*
以上代码可以实现
select * from book bookId in(3,4)
小括号中的内容主要根据实现类中给方法中赋值的数组而定
接口方法的入参类型为int类型集合
foreach标签属性
clooection
循环的类型
open
开头
close
结尾
separator
每次循环的分割
03.foreach 自定义类型
<select id="findByForeachArray" resultType="Book">
select * from book
<where>
bookId in
<foreach clooection="list" open="(" close=")" separator="," item="book">
#{book.bookName}//点出实体类中定义的变量
</foreach>
</where>
</select>
*
以上代码可以实现
select * from book bookId in(3,4)
小括号中的内容主要根据实现类中给方法中赋值的数组而定
接口方法的入参类型为基本类型集合
foreach标签属性
clooection
循环的类型
open
开头
close
结尾
separator
每次循环的分割
12.延迟加载(懒加载)
等会儿再加载,需要访问数据的时候,才加载,就是走数据,发送sql指令,回送SQL结果
*默认情况下关于关联查询对象的加载方式 --》 直接加载
12.1
直接加载(默认为直接加载)
执行对象的 selecti语句,主加载马上执行对关联对象的 select查询
lazyLoadingEnabled false
aggressiveLazyLoading true
12.2
侵入式延迟加载
执行对主加载对象的查询时,不会执行对关联对象的查询。但是当要访问主加载对象的详情时,就会马上执行关联对象的 select查询。
lazyLoadingEnabled true
aggressiveLazyLoading true
12.3
深度延迟加载
执行对主加载对象的查询时,不会执行对关联对象的查询。但是当要访问主加载对象的详情时,不会执行关联对象的 select查询。当程序员主动对关联对象的详情查询时,马上执行关联对象的select查询
lazyLoadingEnabled true
aggressiveLazyLoading false
12.4
注意
01.多条SQL可以实现延迟的效果,单条SQL多表连接查询不能实现
02.在大配置中设置<settings>节点的<setting>中设置
例如
<settings>
<setting name="lazyLoadingEnabled" value="true"><setting/>
<settings/>
***
name
代表属性名称
value
代表属性值
03.lazyLoadingEnabled属性为实现延迟加载的主开关
13.缓存
13.1
一级缓存
01.缓存的底层实现是一个Map,Map的value是查询的结果
02.Map的key,即查询依据,使用的ORM架构的不同,查询依据是不同的
03.MyBatis的查询依据是,Sql的id+SQL语句
04.Hibernate的查询依据是:查询结果对象的id
内置二级缓存
01.由于MyBatis从缓存中读取数据的依据与SQL的id相关,而非查询出的对象。所以,使用二级缓存的目的,不是在多个查询间共享查询结果(所有查询中只要查询结果中存在该对象,就直接从缓存中读取,这是对查询对象的共享,Hibernate中缓存就是为了在多个查询间共享查询的结果,但MyBatis不是),而是为了防止同一查询(相同Sql id,相同sql语句)的反复执行
13.2
一级缓存
基于PerpetualCache的HashMap本地缓存,其生命周期为Session,当Session flush或close之后,该Session中的所有Cache就将清空
二级缓存
二级缓存与一级缓存其机制相同,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用域为Mapper(Namespace),而且可自定义存储源,如Ehcache
*MyBatis中二级缓存一个常量值为true,但是开启条件不只一个,所以不代表二级缓存可用
**
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespace)进行了C/U/D操作后,默认该作用域下所有select中的缓存将被clear
13.3
缓存的分类
网页中
整个页面的缓存
数据操作
数据缓存
泛型集合的形式缓存数据
执行原理
代码中查询语句 <--> 缓存空间 <--> 数据库
举例:
客户端(代码查询语句)首先到缓存空间中查找相应的数据,如果没有再去操作数据库,拿到缓存空间中,在反馈给客户端,下次发同一条请求是直接从缓存空间中获取。
***缓存空间中数据为临时数据
13.4
01.mybatis查询缓存机制。根据缓存区的作用域与生命周期,可划分为两种:一级缓存、二级缓存
02.MyBatis查询缓存的作用域是根据映射文件的namespace划分的,相同的namespace的mapper查询数据放在同一个缓存区域,不同namespace下的数据互补干扰。无论是一级缓存还是二级缓存,都是按照namespace进行分别缓存放的
03.小结
但是一级缓存、二级缓存的不同之处在于,SQLSession一旦关闭,则SQLSession中的数据将不存在,即一级缓存就不复存在。而二级缓存的生命周期与整个应用同步,与SQLSession是否关闭无关。换句话说,一级缓存是在同一线程(同一SQLSession)间共享数据,而二级缓存是在不同线程(不同SQLSession)间共享数据
13.5
查询缓存
主要是为了提高查询访问速度。将用户对同一数据的重复查询过程简化,不再每次均从数据库查询获取结果数据,从而提高访问速度。
13.6
开启二级缓存 --> 三个条件
01.cacheEnabled=true(默认值为true)
在<settings>标签中添加,默认开启。可有可无
02.Mapper文件(小配置文件)中,<cache/>
在小配置中添加<cache/>标签
标签中的属性(例如)
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个FIFO缓存,并每隔60秒刷新,缓存结果对象或列表的512引用,而且返回的对象被认为是只读的
属性和值
eviction
LRU(最近最少使用的,默认值)
移除最长时间不被使用对象
FIFO(先进先出)
按对象进入缓存的顺序来移除它们
SOFT(软引用)
移除基于垃圾回收器状态和软引用规则的对象
WERK(弱引用)
更积极地移除基于垃圾收集器状态和引用规则的对象
FlushInterval(刷新间隔)
可以被设置为任意的正整数,而且它们代表合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size(引用数目)
可以设置为任意正整数,要记住缓存的对象数目和运行环境的可用内存资源数目。默认为1024
readOnly(只读)
属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认为false
03.实体类实现Serializable接口
13.7
关闭二级缓存
01.全局关闭
cacheEnabled=false
02.局部关闭
删除Mapper(小配置)文件中配置
03.在select节点中设置属性usecache为false
<select id=".." resultType=".." usecach="false"></select>
13.8
增删改对二级影响缓存
01.对于二级缓存的清空实际上是对value清空为null,key依然存在,并非将Entey<k,v>删除
02.从DB中进行select查询的条件是
缓存根据不存在这个key
缓存在key对应的Entry,但是value为null
13.9
缓存的命中率
读取二级缓存中的数据时,每次响应的速度都会比前者慢0.1秒
13.10
使用第三方插件框架,实现缓存(ehcache)
01.步骤
引入jar包依赖
<!--EhCache的核心包-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>eheache</artifactId>
<version>2.10.4</version>
</dependency>
<!--Mybatis整合EhCache的包-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
在小配置中添加一个缓存类
<cache type=""></cache>
type指定的是类的全名称
本次指定的是引入的jar包中的EhcacheCache类的全名称
在src下植入ehcache.xml文件
14.配置文件提炼
01.把链接数据库的四大属性提取出来,写在properties文件中
如
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///y2169
jdbc.username=root
jdbc.password=root
02.大配置文件中关联(一)
如
<properties resource="jdbc.properties"></properties>
*大配置和properties文件建立关系
03.大配置文件中关联(二)
如
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
*关联properties文件中的属性