mybatis的性能优化

回顾:

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.(依赖注入)
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 是一个流行的 Java 持久化框架,对于性能优化,以下是一些建议: 1. 使用合适的缓存机制:MyBatis 提供了一级缓存和二级缓存,默认情况下开启了一级缓存。你可以根据具体的业务需求来决定是否启用二级缓存,并且可以配置合适的缓存策略,如使用 Redis 或 Ehcache。 2. 批量操作:对于批量插入、更新或删除操作,可以使用 MyBatis 提供的 `insertList`、`updateList`、`deleteList` 等方法来提高性能,减少与数据库的交互次数。 3. 合理设计 SQL 语句:尽量避免使用 `select *`,只选择需要的字段,以减少数据库传输的数据量。另外,合理设计 SQL 查询语句,避免多表关联查询和复杂的子查询,可以考虑使用分页查询等方式来优化查询性能。 4. 使用延迟加载:MyBatis 支持延迟加载,可以在需要时才加载关联对象,避免一次性加载大量数据。 5. 缓存预热:在系统启动时,可以通过预先查询常用数据并放入缓存中,以提高后续查询的性能。 6. 避免 N+1 查询问题:当一对多关联查询时,避免在循环中执行多次查询,可以使用 MyBatis 的关联查询功能或者使用批量查询方式来解决。 7. 合理配置连接池:MyBatis 使用的数据库连接池对性能也有一定影响,可以根据具体的需求配置合适的连接池参数,如最大连接数、最小空闲连接数等。 8. SQL 优化:使用 MyBatis 提供的 SQL 日志功能,在开发和调试阶段查看生成的 SQL 语句,检查是否存在慢查询、冗余查询等问题,根据需要进行优化。 这些是一些常见的 MyBatis 性能优化建议,根据具体的应用场景和需求,可能会有其他针对性的优化策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值