回顾:
1. mybatis实现增删改查.
1. 查询.
-> parameterType
#{} 或者 ${} 引入抽象方法中传入的参数值.
#{}防止sql注入. ${}字符串的拼接.
-> 模糊查询.
where name like "%"#{key}"%"
where name like concat('%',#{key},'%')
-> 注解传参.
在抽象方法参数前添加注解. @Param("value") String name
sql语句中引入方法参数值. #{value}
-> POJO类传参.
使用parameterType指定传入参数的类型即可.
sql语句中 #{属性名}
-> Map传参.
省略parameterType.
sql语句中 #{key} -> #{key.key.xxx}
2. 添加. (增删改操作的标签,没有提供resultType | resultMap的属性)
如果主键是自增,获取自增后的主键值.
1. 给<insert>添加两个属性即可.
<insert useGeneratedKeys="true" keyProperty="oid的属性名" >
2. 使用mysql提供的函数实现.
<insert>
<selectKey keyProperty="oid的属性名" resultType="Integer|Long">
select LAST_INSERT_ID();
</selectKey>
</insert>
3. 修改和删除.
2. resultMap手动映射.
当实体类的属性和关系表的字段无法自动映射时,使用resultMap手动映射.
<resultMap id="唯一标识" type="抽象方法的返回结果">
<id property="属性名" column="sql语句返回结果的列名" /><!-- 映射oid的 -->
<result property="属性名" column="sql语句返回结果的列名" /><!-- 普通属性 -->
</resultMap>
因为mybatis默认开启了自动映射,如果在不存在嵌套映射的前提下,属性名和字段名一致,省略不写.
3. 一对多,多对一.
R -> 关系表 ->
1. 使用外键维护关系.
2. 使用关系表维护关系.
O -> 实体类 ->
1. 一对多 -> 当前实体类中添加多的一方的集合.
2. 多对一 -> 当前实体类中添加一的一方的对象属性.
3. 多对多 -> 当前实体类中添加对方的集合.
M -> 映射文件
一. 写多表查询的sql语句.
二. 通过resultMap映射一对多,多对一,多对多的映射关系.
<resultMap id="" type="">
<!-- 映射一对多 -->
<collection property="" ofType="">
<!-- 手动映射 -->
</collection>
<!-- 映射多对一 -->
<association property="" javaType="">
<!-- 手动映射 -->
</association>
</resultMap>
4. 动态sql.
if + where
复杂的查询条件,条件基本都可选的.
if -> 当条件不满足要求时, 可不添加当前条件.
where ->
代替where关键字,并且在没有条件时,不添加where关键字.
去除多余的前缀中的一个 and | or
if + set
修改数据.
if -> 当条件不满足要求时, 可不添加当前的赋值 column = ?
set ->
代替set关键字,并且在没有修改的字段时,不添加set关键字.
去除多余的后缀中的一个 ,
if + trim
if -> 当条件不满足要求时,不添加指定内容.
trim -> 自定义前缀,后缀,自定义去除多余的前缀和后缀.
<trim prefix="前缀" suffix="后缀" prefixOverrides="去除前缀and|or" suffixOverrides="去除后缀,">
具体内容
</trim>
foreach
使用in查询或者是批量插入数据时.
<foreach collection="array|list|map-key" open="前缀" separator="间隔" close="后缀" item="每次遍历出来内容的别名">
#{别名}....
</foreach>
choose + when + otherwise
当需要在多个条件中只筛选出一个时,采用choose + when + otherwise.
<choose>
<when test="条件表达式">内容</when>
<when test="条件表达式">内容</when>
<when test="条件表达式">内容</when>
<when test="条件表达式">内容</when>
<otherwise>以上都不匹配,走这</otherwise>
</choose>
一. mybatis的性能优化.
1. mybatis的一级缓存.
一级缓存干嘛的: mybatis的一级缓存是为了减轻数据库压力的.
一级缓存是什么: mybatis的一级缓存实际上就是SqlSession对象中的Executor中LocalCache中一个Map集合.
一级缓存如何工作: 当你使用sqlSession域数据库交互之后,获取一个返回结果之后.
将你的sql语句信息,占位符等信息作为map的key,将查询到的结果作为map的value存储在sqlSession的一级缓存中.
当你再次查询当前数据信息时,就不需要从数据获取,直接SqlSession的Map中获取.
一级缓存的级别: 一级缓存是线程级别的,只有当前用户自己可以使用,其他用户不能使用.
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
Brand brand1 = mapper.findById(1);
Brand brand2 = mapper.findById(1);
sout(brand1 == brand2); -> true
// Brand brand1 = mapper.findById(1);
1. 查询brand1时,通过DefaultSqlSession内部的SimpleExecutor调用query方法查询数据.
2. 执行了SimpleExecutor的query方法时,先通过localCache.getObject(key)去查询数据.(去map中获取)
3. 第一次查询map没有返回,直接调用queryFromDatabase()方法去查询数据,执行了doQuery()查询到了数据之后.
4. 调用localCache.putObject()方法将doQuery()查询到的数据放到了Map中.
5. 返回数据.
//Brand brand2 = mapper.findById(1);
1. 查询brand2时,通过DefaultSqlSession内部的SimpleExecutor调用query方法查询数据.
2. 执行了SimpleExecutor的query方法时,先通过localCache.getObject(key)去查询数据.(去map中获取).
3. 第二次查询,map中有数据,直接返回.
2. mybatis的二级缓存.
二级缓存干嘛的: mybatis的二级缓存也是为了减轻数据库压力的,二级缓存是一个全局的缓存,所有用户都可以使用.
二级缓存是什么: mybatis的二级缓存是SqlSessionFactory工厂中的一个Map集合.
二级缓存如何工作: mybatis在执行查询时,先去二级缓存中查询数据,当二级缓存没有时,再去一级缓存中查询,如果一级缓存中也那么就去数据查询,先将查询到的数据放到一级缓存中,当你执行sqlSession.commit()时候,才会将查询到的数据序列化成byte[]放到二级缓存中.(无论是二级缓存中查询数据,还是插入数据都要经历多个Cache对象,在放到sqlSessionFactory的PerpetualCache中)
二级缓存的级别: SqlSessionFactory级别的.
@Test
public void levelTwoCache(){
//1. sqlSession去数据库查询数据.
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
Brand brand = mapper.findById(1);
sqlSession.commit();
sqlSession.close();
//2. sqlSession2去二级缓存中查询数据.
BrandMapper mapper2 = sqlSession2.getMapper(BrandMapper.class);
Brand brand2 = mapper2.findById(1);
System.out.println(brand == brand2); // false
}
通过二级缓存放数据,或经历一个类似Cache链的操作.
SynchronizedCache.
LoggingCache.
SerializedCache.
LruCache. 算法.最近最少使用. LinkedHashMap.
PerpetualCache.
一级缓存,二级缓存可能出现数据安全问题.
如果有人增删改数据.
为了避免这个问题的放生.
mybatis在指定某个映射文件的增删改时,会清除当前的二级缓存.
因为增删改标签中的flushCache属性默认为true,一致性清空缓存.
select标签的flushCache默认为false,如果设置为true,那么执行这个查询也会清空缓存.
二. spring介绍.
1. spring简介:
spring框架针对javaEE的三层都提供相应的解决方案。
spring是一个后台一站式的框架.
1. controller -> springmvc解决controller层的问题.
2. service -> spring针对事务操作,提供相应处理方案,声明式事务.
3. dao -> 针对dao提供了一个jdbcTemplate,dbutils及其相似. spring又添加了spring-data系列.
spring-data-jpa的dao层框架. (参考了hibernate)
4. spring还是一个框架的粘合剂,第三方框架都需要个spring进行整合.
5. spring提供的IOC. 解耦.
6. spring提供的AOP. 解耦,提升代码的复用性,维护性,扩展性.
7. spring是一个低侵入式的框架.
java的企业级项目一直采用EJB框架.高侵入式框架.
spring之父.
路德·约翰森 = Rod Johnson
轮子理论: 当有一个已经很成熟的技术,不需要重复的开发了,借鉴过来,改一改就直接使用了.
github.
2. 逛官网.
http://spring.io
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WLX9vcua-1573006393738)(img/1569566649286.png)]
1. spring的Core Container核心容器. IOC + DI
2. spring的Test测试模块. spring和junit4整合.
3. spring的AOP,Aspects. AOP,面向切面编程.
4. spring的JDBC数据库交互. spring的JdbcTemplate.
5. spring的Transaction声明式事务. 处理事务问题.
6. spring的Web模块. 通过一个小demo完成springmvc中提供的全部组件功能.
三. spring的IOC介绍.
1. 介绍IOC思想.
java的程序中,是由N多个对象组成的.是由N多个对象相互配置,完成项目中的某一个功能.随着对象的增多,关系的混乱,当我去修改了某一个对象的信息时,可能导致其他的N个多个对象也受到影响.程序的耦合度过高.
高内聚,低耦合.
在1996年,由一个mattson的大拿,提出了一个思想.IOC思想.
目的 -> 降低对象之间的耦合性.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ccXcc3LY-1573006393739)(img/1569567455186.png)]
2. DI
在2004年马丁大神,观摩了一波IOC思想,马丁认为IOC这个词不准确.
为IOC的思想起了一个名字 -> DI -> 依赖注入.
3. IOC和DI的定义:
将创建对象的权利反转给IOC容器,并由IOC容器管理对象之间的依赖关系.
IOC 即 控制反转是Inversion Of Control的简写.
DI 即依赖注入时dependency Injection的简写.
他们两个都在表达
将创建对象的权利反转给IOC容器,并由IOC容器管理对象之间的依赖关系. -> 解耦
只不过侧重点不同.
四. spring的IOC.(控制反转)
1. 创建项目.
2. 导入依赖.
1. spring-beans
2. spring-core
3. spring-context
4. spring-expression language
5. commons-logging
6. junit
3. 准备POJO类.
public class User {
private String name;
private Integer age;
}
4. 编写spring的配置.
1. idea默认支持spring的,当你导入了spring的依赖后,直接直接创建spring Config配置文件.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id : 当前bean标签的唯一标识-->
<!-- class : 被IOC容器创建的类的全路径-->
<bean id="user" class="com.qf.entity.User" />
</beans>
5. 测试.
// 测试spring创建对象
@Test
public void inDoor(){
// spring创建对象的原理.
// 通过反射创建对象.
// SAX解析XML文件.
// IOC容器就是一个工厂. -> 工厂模式.
//1. 加载配置文件并获得spring工厂.
// ApplicationContext可以看做成spring的工厂,而spring工厂的顶级接口是BeanFactory.
ApplicationContext ac =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//2. 获取user对象.
User user = (User) ac.getBean("user");
//3. 输出
System.out.println(user);
}
五. spring的IOC创建对象细节.
name="" -> name和id一模一样,都是唯一标识. (不使用即可).
scope=""
作用域:
singleton(默认值)单例 -> 整个IOC容器中只有当前类的唯一一个实例.
prototype原型|多例(Struts2) -> 每个线程都获得当前类的一个全新实例.
request请求 -> 一次请求创建一个.
session会话 -> 一次会话创建一个.
global-session全局会话 -> 为了保证多个服务,也在一次会话中只有一个实例(基本不用)
lazy-init=""
懒加载: (懒加载只针对单例有效.) 解决循环依赖的进阶问题.
true 用时间换空间 -> 懒汉
false(默认值) 用空间换时间 -> 饿汉
depends-on=""
依赖其他实例,保证初始化当前实例前,先初始化指定实例.
depends-on="实例唯一标识,..."
init-method=""
对象初始化时,执行.
destroy-method=""
对象销毁时,执行.
-> spring容器中对象的简单声明周期. 创建对象 -> init-method -> destroy-method
----------------------------------------------------------------------------------------
(spring容器,IOC容器,spring工厂,IOC工厂是一个东西)
factory-bean=""
factory-method=""
静态工厂创建对象.
提供了static静态方法.
<bean id="对象实例标识" class="静态工厂" factory-method="静态方法" />
实例工厂创建对象.
提供非静态方法.
<bean id="实例工厂标识" class="实例工厂" />
<bean id="对象实例标识" factory-bean="实例工厂标识" factory-method="非静态方法" />
(spring容器,IOC容器,spring工厂,IOC工厂是一个东西)
factory-bean=""
factory-method=""
静态工厂创建对象.
提供了static静态方法.
实例工厂创建对象.
提供非静态方法.
# 六. spring的DI.(依赖注入)