1.mybatis工作原理
一、相较于Hibernate,mybatis的优势在哪里?
Hibernate缺点:
1、运行效率低,内存占用比较严重
2、针对单一对象的增删改查,适合Hibernate,而Hibernate在批量操作时处于弱势
3、虽然Hibernate引入一二级缓存、lazyload、查询缓存等更多优化空间(对于那些改动 不大且经常使用的数据,可将他们放入缓存中),但Hibernate对于持久层封装过于完 整,导致开发人员无法对sql进行优化,不适用于大型项目
mybatis优点:
1、代码量大大减少,开发效率高
2、 MyBatis相当灵活,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统 一管理和优化,并可重用
3、运行效率高
二、mybatis原理
下面是mybatis的一个原理图,看懂这个图对理解mybatis工作原理很重要:
上面的原理图看的不是很清晰,下面再详细介绍一下mybatis的主要成员:
1、Configuration
MyBatis所有的配置信息都保存在Configuration对象之中,配置文件的大部分配置都会存储到该类中
2、SqlSession(工厂模式创建出来)
作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
3、Executor
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等
4、ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
5、ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
6、TypeHandler
负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
7、MappedStatement
MappedStatement维护一条<select|update|delete|insert>节点的封装
8、SqlSource
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
9、BoundSql
表示动态生成的SQL语句以及相应的参数信息
下面介绍一下mybatis的工作流程:
首先,mybatis的增删改查这些数据库操作都是基于sqlsession类的,SqlSession又是由SqlSessionFactory类创建出来的(这里采用了java设计模式中的工厂模式),而SqlSessionFactory是由SqlSessionFactoryBuilder创建的,SqlSessionFactoryBuilder要想创建SqlSessionFactory,必须要有原料(即mybatis配置文件),下面是创建SqlSession的代码:
//加载classpath路径下的mybatis配置文件
InputStream in=Resources.getResourceAsStream(“mybatis-config.xml”);
//根据加载配置文件产生的输入流,来创建一个SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//根据SqlSessionFactory创建SqlSession
SqlSession session = sessionFactory.openSession();
下面介绍这几个重要对象的作用域和生命周期
1、SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的 XML 解析资源开放给更重要的事情。
2、SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次。因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式
3、SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。sqlSession在每次用完之后必须关闭它
三、mybatis缓存机制
1、一级缓存
MyBatis一级缓存是基于sqlSession的,sqlSession对象有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象无法访问。一级缓存默认是开启的,且无法关闭。增删改操作会清空当前sqlSession里的缓存
2、二级缓存
MyBatis二级缓存是mapper级别的缓存,同一个namespace共用这一个缓存,所以对SqlSession是共享的,二级缓存是默认关闭的。
如何配置二级缓存?只需要在sql映射文件中添加即可
测试代码:
/*
- 注意:被缓存的数据要实现序列化接口(在这里将Book.java实现序列化接口),否则会出现异常
- 另外,当某一个sqlSession修改了共享的缓存数据之后,二级缓存也会清空
*/
SqlSession session_1 = MyBatisUtil.getSession();
BookDao mapper_1 = session_1.getMapper(BookDao.class);
mapper_1.listBook();
//注意,必须提交才能将数据放进二级缓存
session_1.commit();
SqlSession session_2 = MyBatisUtil.getSession();
BookDao mapper_2 = session_2.getMapper(BookDao.class);
mapper_2.listBook();
这里只是为了测试二级缓存的原理,所以MyBatisUtil类如何获取SqlSession的代码就没有粘贴进来了。
Mybatis缓存参考
https://www.cnblogs.com/happyflyingpig/p/7739749.html
https://tech.meituan.com/2018/01/19/mybatis-cache.html
框架使用问题汇总
【Spring Boot】1.解决IDEA中springboot整合mybatis中出现的Invalid bound statement(not found)的问题
https://blog.csdn.net/benben513624/article/details/81076182
2.Hibernate 工作原理
hibernate 核心流程
从上图中,我们可以看出Hibernate六大核心接口,两个主要配置文件,以及他们直接的关系。Hibernate的所有内容都在这了。结合简单的代码描述来进行说明:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作 session.save(XXX).
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory
Hibernate的缓存机制
Hibernate缓存分为一级缓存和二级缓存
一级缓存:每次hibernate跟数据库打交道时,都是通过session来对要操作的对象取得关联,然后在进行操作,那么具体的过程是什么样的呢?
1、首先session将一个对象加入自己的管理范围内,其实也就是把该对象放入自己的一级缓存中,例如,session.save(xxx);这个语句就是将xxx保存在自己的一级缓存中,等待事务提交后,hibernate才真正的发sql语句,对数据库进行操作。注意:session进行操作的时候,是将对象加入自己的一级缓存,并不是就直接跟数据库打交道了。session.save()操作就是一级缓存的过程。这边文章详细的介绍了一级缓存的相关信息:http://www.cnblogs.com/whgk/p/6103038.html
二级缓存:hibernate二级缓存是由第三方提供以插件的形式存在,常用的缓存实现有Ehcache、oscache.
参考
https://blog.csdn.net/xiaofbing/article/details/70274154
hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory
为什么要用hibernate:
- 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
- hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
- hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
Hibernate是如何延迟加载?get与load的区别
-
对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。
-
Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
这里get和load有两个重要区别:
如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。
总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
说下Hibernate的缓存机制:
Hibernate缓存的作用:
Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据
Hibernate缓存分类:
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存
Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 常量数据
不适合存放到第二级缓存的数据?
1经常被修改的数据
2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
3 与其他应用共享的数据。
Hibernate查找对象如何应用缓存?
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存
删除、更新、增加数据的时候,同时更新缓存
Hibernate管理缓存实例
无论何时,我们在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。
当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
Hibernate的查询方式
Sql、Criteria,object comptosition
Hql:
1、 属性查询
2、 参数查询、命名参数查询
3、 关联查询
4、 分页查询
5、 统计函数
如何优化Hibernate?
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
6. 继承类使用显式多态
7. 表字段要少,表关联不要怕多,有二级缓存撑腰
hibernate的开发步骤:
开发步骤
1)搭建好环境
引入hibernate最小的jar包
准备Hibernate.cfg.xml启动配置文件
2)写实体类(pojo)
3)为实体类写映射文件"User.hbm.xml"
在hibernate.cfg.xml添加映射的实体
4)创建库表
5)写测试类
获得Configuration
创建SessionFactory
打开Session
开启事务
使用session操作数据
提交事务
关闭资源
3.Spring 详解
特点:
轻量级、容器、框架集合、
控制反转(IOC 技术促进低耦合,四种依赖注入方式 a.带参数构造方法 b.setter 方法注入 c.静态工厂方法注入 d实例工厂方法)、
面向切面(AOP 业务逻辑和系统逻辑分开,将影响多个类的公共行为封装到可重用模块及Aspect 切面)
aop主要场景:权限、缓存、调试、持久化等
Spring两种方式生成代理对象 JDK 动态代理和CGlib 代理
Spring 常用注解:
1.@Controller 标记在一个类上控制层,框架扫描有此注解的类并找对应RequestMapping 注解的方法
2.RestController 相当于@Controller 和@responseBody 组合效果
3.@Component 当组件不好归类时用此注解
4.@Service 标注业务层组件
常用第三方框架
Spring bean 的作用域:singleton (单例)、prototype (原型模式 每次使用创建)、request (一次请求一次实例)、session(一次session 中只有一个实例)、global session 全局
权限问题
Java安全框架Shiro和Spring Security对比
1.Shiro三个核心组件:Subject, SecurityManager 和 Realms.
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行,是shiro的心脏。
realm:域,领域,相当于数据源,通俗意义的DAO层,通过realm存取认证、授权相关数据。
4.SpringMVC 详解 SpringMVC流程
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
Spring 面试题汇总
https://blog.csdn.net/qq_36520235/article/details/88257749
5.SpringBoot 原理及介绍
https://www.cnblogs.com/jstarseven/p/11087157.html
springboot 启动过程
https://www.jianshu.com/p/603d125f21b3
如下两种框架区别
https://blog.csdn.net/valada/article/details/80892573
項目配置健康檢查
https://www.jianshu.com/p/c6d172577c3d
https://blog.csdn.net/pengjunlee/article/details/80235390
6.Spring Cloud 原理及介绍
springcloud是微服务架构的集大成者,将一系列优秀的组件进行了整合。基于springboot构建。主要分为5大部分
服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon
断路器——Netflix Hystrix
服务网关——Netflix Zuul
分布式配置——Spring Cloud Config
参考
https://blog.csdn.net/oldshaui/article/details/90675149
Eureka原理
操作实例 https://www.cnblogs.com/haha12/p/11607276.html
https://blog.csdn.net/zhuyanlin09/article/details/89598245
eureka 是Netflix 子模块是基于Rest的服务,只需要服务标识即可访问到服务类似Dubbo的Zookeeper 使用时服务Eureka客户端连接到Server 并维持心跳检测。
Eureka包括两个组件:Eureka Server和Eureka Client
Eureka 可以设置自我保护模式防止网络问题引起的短时间多个服务心跳异常
Ribbon 负载均衡工具
https://blog.csdn.net/qq_20597727/article/details/82860521
提供一系列配置项如超时、重试等,主要是配置列出Load Balancer .
Bibbon会基于单轮询和随机连接等去连接这些机器。
Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端实现负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中Load Balancer后面的所有机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
参考文章 https://blog.csdn.net/u013087513/article/details/79775306
Fegin 工作原理
Feign是一种声明式、模板化的HTTP客户端(仅在Application Client中使用)
https://blog.csdn.net/u010066934/article/details/80967709
https://www.cnblogs.com/jing99/p/11618937.html
Zuul 路由,Zuul 服务最终还是会注册到Eureka上
Spring Cloud Config 分布式配置
微服务下的链路追踪(Sleuth+Zipkin)
https://blog.csdn.net/pengjunlee/article/details/87797969
7.Dubbo原理及介绍
https://segmentfault.com/a/1190000019896723