Mybatis&JPA

1.ORM思想、MyBatis概述、日志框架、OGNL

         1.1 框架

:是一系列jar包,其本质是对JDK功能的扩展(SDK),是一组程序的集合。

1.2 ORM思想

                     对象关系映射(Object relational Mapping):主要解决对象-关系的映射

                            是为了解决面向对象和关系型数据库不匹配的问题的技术。

                            简而言之,ORM就是通过就是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系型数据库中

1.3 常见的ORM框架:

                     JPA:并非ORM框架,而是ORM规范,由各大ORM框架进行实现

                     Hibernate、Mybatis

                    

1.4 Mybatis概述及架构图

                     mybatis是持久层框架,支持定制化sql、存储过程、高级映射,几乎避免了所有的JDBC代码和手动设置参数及获取结果集,使用XML或注解来配置映射。

1.5 Mybatis 核心组件

                     SqlSessionFactoryBuilder(构建器):创建SqlSessionFactory对象

                     SqlSessionFactory(会话工厂):创建SqlSession对象

                     SqlSession(会话):好比是Connection。

                     Executor(执行器):SqlSession不能直接操作数据库,需要Executor来完成,此接口有两个实现,缓存执行器(缺省)、基本执行器

                     MappedStatement(映射语句):封装执行sql语句时的信息,例如:SQL、输入参数、输出结果

              1.6 Mybatis原理图:

                            mybatis配置文件/连接池/事务等->会话工厂->会话->执行器->映射语句->DB

                            更底层的原理图:

                           

                            SqlSession->Executor->StatementHandler->ParameterHandler、ResultSetHandler->TypeHandler

                                                                                                                                                                                             -> JDBC->DB

                            Configuration->MappedStatement(SqlSource、ResultMap)->BoundSql   

                            涉及对象说明:

                                   SqlSession:表示和数据库交互的会话,完成数据库增删改查功能

                                   Executor:负责sql语句的生成和查询缓存的维护

                                   StatementHandler:封装了JDBC的DML、DQL操作、参数设置

                                   ParameterHandler:用户传入参数转换为JDBX需要的参数值

                                   ResultHandler:结果集中的数据封装到list集合中

                                   TypeHandler:java类型和JDBC类型的相互转换

                                   MappedStatement:维护了一条<insert|update|delete|select|>节点的封装

                                   SqlSource:根据用户传入的参数生成SQL语句,并封装到BoundSql中

                                   BoundSql:封装SQL语句和参数的信息

                                   Configuration:Mybatis全局配置对象,封装了所有配置信息

1.7 获取mybatis:pom中引入org.mabytis.mybatis

1.8 全局配置文件

一般放在resource目录下,通常命名为 mybatis-config.xml(包含全局配置、属性配置、插件配置、配置环境信息、关联映射文件)

1.9 映射文件

例如XXXMapper.xml。主要包含列和对象的映射,以及insert、delete、update、select 标签

1.10 Mybatis和日志集成配合使用

                     常见的日志框架:Log4j、Log4j2、Logback、Slf4j。Apache提供的日志规范即日志门面,有了日志门面后,需要用户自行选择第三方的日志组件作为具体实现。

                     采用最多的日志技术:Slf4j日志门面和Log4j2日志实现

                     日志级别:ERROR>WARN>INFO>DEBUG>TRACE;如果设置日志级别为INFO,则日志级别为ERROR、WARN、INFO的日志信息会被输出

                     日志级别设置越低、输出内容越详细

                     日志文件组成:Log4j2主要由 Loggers、Appenders、Layout 组成。

                     Loggers:日志记录器,控制日志的输出及输出级别

                     Appenders:输出控制器,指定日志输出的输出方式(输出到控制台还是文件等)

                     Layout:日志格式化器,控制日志信息的输出格式

                     日志使用:pom文件中引入log4j、mybatis配置文件中全局配置、定义日志文件

1.11 作用域和生命周期

                     SqlSessionFactoryBuilder:此类可被实例化、使用和丢弃,一旦创建SqlSessionFactory对象后,就不再需要。所以此对象放在局部作用域中较合适

                     SqlSessionFactory:一旦被创建就应该在应用的运行区间一直存在(单例),最佳作用是应用作用域。

                     SqlSession:每个线程都有自己的SqlSession实例,非线程安全的,因为不能被共享,最佳作用域是请求作用域。

1.12 #和$的异同

              相同点:都可以获取对象的信息

              不同点:使用#传递的参数会先预编译转换为?占位符,通过$会将解析的数据直接作为SQL的一部分

                          #好比PrepareStatement,不会导致sql注入问题,相对安全;$好比Statement,可能会导致SQL注入,相对不安全

              如何选择:需要设置占位符的参数,全部使用#;如果传递过去的对象参数作为SQL的一部分,则使用$。例如分组、排序等           

                    

1.13 Mybatis注解开发,

就不需要XXXMapper.xml了。主配置文件中的mapper标签需要修改为对应Mapper文件全路径

              @Insert("sql")、@Delete("sql")、@Update("sql")、@Select("sql")

1.14 多对一数据结构最优查询方案

                     方案一:查询到人员信息之后,再根据人员信息表中的部门id查询到部门信息

                     方案二:resultMap中配置association元素(配置单一元素(非数组、集合)的关联对象),将另一个mapper的sql通过association标签嵌入到当前mapper中

                     方案三:只需要保留一个mapper,但是使用join进行内联映射-多表关联查询

                     额外SQL的N+1问题:当所有员工,每个员工的部门ID都不一样时,可先查询出所有员工,然后将员工的部门ID提取出来组成Set,然后根据所有部门ID查询所有部门,最后遍历员工信息,将部门赋予员工即可

                    

                     一对多数据结构最优查询方案

                     方案一:使用collection标签

1.15 懒加载(延迟加载)、Lazy Load。默认懒加载是禁用的

                     产生原因:为了避免一些无谓的性能开销提出的方案

                     定义:当真正需要数据的时候,才会真正执行sql去查询数据

                     mybatis运行期的属性配置,在settings文件中配置

                     开启懒加载只需将settings文件中的lazyLoadingEnabled设置为true即可

1.16 mybatis缓存机制

                     使用缓存可以更快获取数据,mybatis和hibernate一样,也有一级缓存和二级缓存。一级缓存默认开启,二级缓存需要手动开启。

                     一级缓存:也称本地缓存,默认开启,不能关闭。是基于PerpetualCate的hashmap本地缓存,存储作用域是SqlSession级别,当Session

                     刷新或者close之后,该SqlSession中的缓存就将清空。SqlSession之间不共享一级缓存。同一个SqlSession会话,发起1条sql语句,才会使用一级缓存。

                     可以使用SqlSession.clearCache()或增删改操作,都会清空缓存。

                     一级缓存是基于[namespace:sql语句:参数]作为map的key,查询返回的语句作为value保存的

                    

                     二级缓存:也称查询缓存,需要手动配置或开启,也可使用第三方缓存框架,例如EhCache、Redis等

                     也是采用基于PerpretualCache的hashmap对象。不同在于作用域为Mapper(Namespace)级别,多个SqlSession是共享数据的,并且可自定义数据源,如EhCace、Redis等。

                     开启二级缓存情况下,在一级缓存数据清空或提交之前,会转存到二级缓存中继续存在。

                     在二级缓存中,两个对象是分别放在两个独立的Map中的(各自的缓存空间)

                     通常会放到二级缓存中的数据:经常查询;很少修改;不会并并发访问的数据

                     不适合放到二级缓存的数据:经常被修改

                     开启二级缓存步骤:setting文件中设置cacheEnabled为true;sql映射文件中添加cache标签。属性有eviction、flushInterval、size、readOnly

                                                 eviction表示回收策略:有以下几种选项

                                                        LRU:默认值、移除最长时间不被使用的对象

                                                        FIFO:按照对象进入缓存的顺序来进行移除

                                                        SOFT:移除基于垃圾回收器状态和软引用规则的对象

                                                        WEAK:移除基于垃圾回收器状态和弱引用规则的对象

                                                

                                                 flushInterval:表示刷新间隔,可设置为任意正整数的毫秒数。默认无刷新间隔

                                                 size:引用数目,默认值1024

                                                 readOnly:只读属性,true或者false(默认)。只读缓存会给所有调用者返回缓存对象的相同实例。

                                                

                     二级缓存的使用:实体类必须实现序列化接口。

                     二级缓存使用流程:当一个sqlsession执行1个select后,关闭session,会将查询结果保存至二级缓存中。另一个sqlsession查询相同数据时,会先在一级缓存中查询,如果没有会进入二级缓存查询,找到了就返回,从而减轻数据库的压力提高了性能。

                     注意事项:当sqlsession执行了DML操作(insert、delete、update)后,mybatis会清空缓存中的所有数据,可以保证缓存数据和实时数据是一致的,避免出现脏读。

                     基于[namespace:sql语句:参数]作为map的key,查询返回的语句作为value

                     注解开启二级缓存:在Mapper上添加注解@CacheNamespace("blocking = true ")

                     mapper.xml文件中每个select标签都可以使用useCache属性,默认为true(如果二级缓存开启,则二级缓存生效)。如果为false,即便二级缓存开启,也不会生效。但是一级缓存是没问题的。

                   增删改查都可以设置 flushCache 属性。增删改此属性默认为true,执行增删改后,会将原来的一、二级缓存全部删除。查询此属性默认为false,如果查询此属性为true,则禁用一切属性。

                     全部变量 localCacheScopo:SESSION (默认) 开启了一级缓存;STATEMENT:如果设置为此值,相当于关闭一级缓存。

利用自身本地缓存结合redis实现分布式缓存

1.redis实现分布式缓存

       缓存:内存中的数据

       内存中数据特点:读写快、断点立即丢失

       缓存解决问题:提高吞吐量,提升响应速度(效率),缓解数据库压力

       适用场景:针对数据库中不常变更的数据适合保存至缓存,如省市县、基础数据

       本地缓存和分布式缓存的区别:

              本地缓存:存储在应用服务器内存中。mybatis的一级缓存和二级缓存保存在服务器内存中

              分布式缓存:存储在当前应用服务器内存之外的数据。redis缓存不局限于某个应用

       集群和分布式

              集群:将同一种服务创建多个节点共同对外提供服务的过程

              分布式系统;多个不同服务集群组成的系统,是共同对系统提供服务

       利用mybatis缓存结合redis实现分布式缓存

              自定义缓存类,实现mybatis提供的Cache接口

       2.搭建springboot和mybatis整合

              全局配置文件中定义<setting name="cacheEnabled",value=""true>,具体的xml中添加</cache>,对应查询语句上使用 useCache="true",实体类实现序列化接口即可开启二级缓存

              二级缓存也只局限于当前的应用程序,当程序停止(JVM关闭),缓存就不存在了。再次启动程序,还是去数据库中查询

              mybatis缓存默认是适用PerpetualCache implements Cache来实现的,底层是HashMap,适用HashMap保存缓存数据时,Key为[nameSpace:SQL:参数],value是查询返回的语句

       3.自定义RedisCache缓存

              mapper.xml中设置<cache type="RedisCache所在路径">

              自定义RedisCache实现Cache接口,重写getId、getObject、putObject等关键方法,重写方法中适用redis进行数据的读写

              最终首次读取从数据库读,后续就从redis读取了,即便程序结束再重启,依旧是从redis中读取数据

              当执行增删改会执行RedisCache的clear方法,清除redis中的缓存,防止缓存中数据是没有更新过的脏数据

       4.多表查询出现的缓存问题

              当user表中包含emp表的数据,后面对emp数据进行了更改,redis中emp的缓存数据删除,但是缓存中user的数据还是包含emp的数据,便出现和redis和数据库数据不一致

              优化策略:使用<cache-ref namespace="com.zy.dao.UserDao"/>, 将多个有关联关系的表的缓存放到了一起;也可在emp数据清空时,将关联表的user数据也清空

       5.缓存优化策略

              key长度不要太长,使用MD5散列算法

1.17 ORM概述

                     ORM(Object-Relation-Mapping)表示对象关系映射,在面向对象软件开发中,通过ORM可以将对象映射到关系数据库中。简而言之,ORM就是建立实体类和数据库表之间的关系,从而达到操作实体类就是操作数据库表的目的。

                     使用ORM的原因:大大减少重复性的数据库访问层代码

                     常见ORM框架:Mybatis、ibatis、Hibernate、JPA(规范)

1.18 Hibernate和JPA的概述

                     Hibernate:全自动的ORM框架,自动生成SQL语句、自动执行

                     JPA:全称为:Java Persistance Api,即java持久化API。SUN公司推出的基于ORM的规范,内部由接口和抽象类构成。

                     JPA和Hibernate的关系:JPA是规范,Hibernate是JPA的实现

1.19 JPA、Hibernate、SpringDataJpa之间的关系

                     JPA是规范,

                     Hibernate是JPA的实现,

                     SpringDataJpa是spring 提供的简化JPA开发的框架,是JPA规范的再次封装,底层还是使用Hibernate的JPA实现

1.20 JPA API介绍

                     Persistence对象:主要是通过此类的静态方法createEntityManagerFactory用于获取EntityManagerFactory对象

                     EntityManagerFactory:此接口主要用于创建EntityManager 实例。线程安全,但是创建非常消耗资源,所以只需要确保工程中只存在一个EntityManagerFactory(单例)即可

                     EntityManager :此对象是完成持久化操作的核心对象

                     EntityTransaction :完成事务操作的核心对象

              1.21 Spring Data JPA 内部原理剖析

                     自定义Dao无方法就可以使用很多方法的原因:继承了JpaRepository和JpaSpecificationExecutor,可使用这两个接口的所有方法

                     SpringDataJPA的实现过程:注入的Dao对象,本质上是通过JdkDynamicAopProxy生成一个代理对象SimpleJpaRepository,借助此对象中对应的方法,通过EntityManagere完成数据库的操作

                    

                     四种查询方式:SpringDataJPA定义的方法;JPQL;SQL;方法命名规则查询

mybatis-plus

todo

参考资料:https://blog.csdn.net/m0_46313726/article/details/124187527

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值