2019年4月份
4月1日
为什么要使用 hibernate?
使用Hibernate很大程度上取决于2点优势。
(1)Hibernate对jdbc进行了封装,简化了我们操作Dao层的编码工作。
(2)Hibernate提供了优秀的缓存机制,可以帮助我们的程序跑得更快。
什么是ORM
ORM是对象关系映射。就是把数据库中的字段,映射到Java实体的属性里面。
常用的ORM框架有Mybatis与Hibernate。
Hibernate与Mybatis的区别
我就个人经历过的项目而言,我对下面的几点很有体会。
(1)速度。如果一个项目没有复杂的SQL语句,那么使用Hibernate显得很容易。Hibernate因为封装了基本的增删改查的SQL语句,所以速度很快。而Mybatis对于开发者更加灵活,它是自己编写的SQL语句,所以可以适应一些复杂的SQL场景。因此,看项目。如果项目不复杂,使用Hibernate。如果项目较为复杂,使用Mybatis。
(2)难度。Hibernate有一套很成熟的HQL语句,而且Hibernate还有其它非常多的配置,学习难度比Mybatis大许多。
hibernate 中如何在控制台查看打印的 SQL 语句?
在配置文件里面,把hibernate.show_SQL设置为true就行了,但是可能会降低一定的性能。
hibernate 有几种查询方式?
原生SQL、HQL、条件查询。
hibernate 实体类可以被定义为 final 吗?
可以加上final,以前我试过。不过被final修饰的类不能被继承,那么cglib动态代理就不能创建这个类的子类。所以相关的性能优化,延迟加载,将被舍弃掉。
在 hibernate 中使用 Integer 和 int 做映射有什么区别?
Integer可以映射为null,但是int不能映射为null
hibernate 是如何工作的?
读取配置文件
创建SesssionFactory
创建Session
创建事务
持久化
提交事务
关闭session
关闭sessionFactory
get()和 load()的区别?
get不支持延迟加载,而load支持延迟加载。
说一下 hibernate 的缓存机制?
一级缓存是session缓存。session缓存是事务级别的缓存,因为session对象的生命周期通常对应着数据库中的一个事务。举个例子,如果我们调用get方法查询并返回了一个对象,第二次查询这个对象的时候就会返回session缓存中已经存在的这个对象,而不用在去数据库中查询。一级缓存是由Hibernate直接管理的,因此我们不能手动关闭一级缓存。
二级缓存是SessionFactory缓存。SessionFactory缓存是进程级别的缓存,因为sessionFactory对象的生命周期与项目相同。二级缓存中的缓存对象可以被整个应用程序中的任何Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。
hibernate 对象有哪些状态?
瞬时状态:直接 new 出来的对象,该对象还没被持久化(没保存在数据库中)
持久化状态:当调用 Session 的 save/get/load 等方法的时候,对象就是持久化状态。
游离状态:Session 关闭之后对象就是游离状态。
hibernate 实体类必须要有无参构造函数吗?为什么?
因为Hibernate需要调用反射的相关API,所以会调用对象的无参构造函数创建对象。所以要求实体要提供一个无参的构造函数。
4月2日
MyBatis 中 #{}和 ${}的区别是什么?
井号是预编译的SQL语句,解析后的SQL语句的参数会带上引号。
美元符号的相当于是拼接SQL语句,所以不会带上引号。
一般来说,在动态排序中,使用美元符号才能达到要求。比如 select * from 表 order by ${id}
另外值得一提的是,美元符号的因为是SQL语句的拼接,可能会导致一些SQL注入的风险。所以要对用户的输入进行正则表达式的校验。
MyBatis的分页
第一种是自己手动编写分页,在MySQL中使用limit关键字。
第二种是使用PageHelper分页插件,调用startPage()方法来开启分页。分页插件的办法,我在毕业设计中使用过。
第三种是逻辑分页,它是一次性查询很多数据,然后在数据中再进行检索。这种办法效率低,占用内存大。
MyBatis 是否支持延迟加载?
MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 即可。
懒加载原理
一个对象里面持有另外一个对象。比如A对象持有B对象。我们查询出来了A对象,但是会发现B对象是一个null。只有调用B对象的时候,才会去数据库查询出B对象。这就是懒加载。
一言以蔽之:什么时候调用,什么时候查询。
MyBatis 的一级缓存和二级缓存
Mybatis的一级缓存是基于同一个SqlSession的缓存。就是会把查询出来的数据保存下来,下次再查询的时候,先看看缓存里面有没有,如果有的话,就不查询数据库了。如果没有,才需要查询数据库。
Mybatis的二级缓存是基于同一个namespace下的所有SqlSession。同一个namespace下的SqlSession查询到的数据将会共享。同样的,获取数据的时候,先从缓存中获取,如果没有,才查询数据库。
4月2日
从RabbitMQ 结构图来看,有如下几个 过程:
1. 消息从生产者Producer发送到交换机Exchange
2.交换机根据路由规则将消息转发到相应队列
3. 队列将消息进行存储
4.消费者订阅队列消息,并进行消费
RabbitMQ 的使用场景有哪些?
(1)异步处理。一般的注册流程中,可能会有把注册信息插入数据库、发送注册邮件、发送注册短信这三个步骤。而发送注册邮件和发送注册信息可以使用RabbitMQ进行异步处理。这样可以减少客户端等待的时间。客户端实际等待的时间只有数据写入数据库的时间。剩下的交给消息中间件异步处理即可。
(2)流量削峰。比如在抢购系统中,如果一瞬间有大量的用户请求,先把这些用户请求写入到消息中间件中,然后再进行处理。如果请求数量超过消息中间件的最大队列,那么就提示用户再等一会再来操作。这样可以防止我们的系统因为过大的负载而崩溃的情况。
RabbitMQ 有哪些重要的角色?
生产者,用于创建消息并把消息发送给消息队列。
代理:用来保存消息,并把消息投递给指定的接收者。
消费者:用来接收消息,并根据消息进行进一步业务处理。
RabbitMQ 有哪些重要的组件?
连接管理器ConnectionFactory,我们的应用程序与RabbitMQ建立连接的管理器。
Exchange(交换器):用于接受、分配消息。
Channel(信道):消息推送使用的通道。
Queue(队列):用于存储生产者的消息。
--------------------------------------------------------------------------------------------------------------------------
RoutingKey(路由键):用于把生成者的数据分配到交换器上。
BindingKey(绑定键):用于把交换器的消息绑定到队列上。
RabbitMQ 中 vhost 的作用是什么?
每一个RabbitMQ都能创建很多vhost。这个vhost可以理解为虚拟主机。就是一个 mini版本的RabbitMQ,拥有自己的交换器与队列。
RabbitMQ 的消息是怎么发送的?
客户端必须连接到 RabbitMQ 服务器才能发布和消费消息。
首先客户端和 rabbit server 之间会创建一个 tcp 连接。
一旦 tcp 打开并通过了认证,你的客户端和 RabbitMQ 就创建了一条符合标准协议的信道(channel)
后来的发消息和接收消息都是由这信道完成的。
RabbitMQ 怎么保证消息的稳定性(中间网络断开怎么办? )?
提供了事务的功能。缺点是 事务模式会极大的消耗RabbitMQ的性能。
通过将 channel 设置为 confirm(确认)模式。类似于TCP三次握手一样,消息发送方与消息接收方互相发送确认报文。只有接收方确认了已经接收到消息,那么才认为数据成功发送。否则认为发送失败,需要重新发送消息。
RabbitMQ 怎么避免消息丢失?
把消息持久化磁盘,保证服务器重启消息或者意外宕机不丢失。
ACK确认机制,消费端消费完成要通知服务端,服务端才把消息从内存删除。
要保证消息持久化成功的条件有哪些?
1) Exchange 设置持久化
2)Queue 设置持久化
3)Message持久化发送
RabbitMQ 持久化有什么缺点?
因为使用的是磁盘而非内存存储,从而降低了吞吐量。
RabbitMQ 有几种广播类型?
topic:路由器根据正则,把消息投递到指定的队列中。
direct(默认方式):就是根据路由键的Key进行发送。如果Key一致,路由器就把数据投递到这个队列中。
fanout:直接把队列绑定到路由器。路由器在收到消息后,直接把消息投递到队列中,不需要路由键。