Mybatis仅支持assaciation关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载LazyLoadingEnabled = true | false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的SQL,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
122. 说一下 mybatis 的一级缓存和二级缓存?一级缓存:基于PerpetualCache 的HashMap 本地缓存,其存储作用域为Session,当Session flush 或close 之后,该Session中的所有Cache就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用域为Mapper(Namespace),并且可自定义存储源,如Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)进行了C/U/D操作后,默认该作用域下所有select中的缓存将被clear。
123. mybatis 和 hibernate 的区别有哪些?- Mybatis和Hibernate不同,它不完全是一个ORM框架,因为Mybatis需要程序员自己编写SQL语句。Mybatis直接编写原生态SQL,可以颜色控制SQL执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一旦需求变化,要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套SQL映射文件,工作量大。Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用Hibernate开发可以节省很多代码,提高效率。
SimpleExecutor:
每执行一次update或select,就开启一个statement对象,用完立刻关闭statement对象。
ReuseExecutor:
执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简而言之,就是重复读Statement对象。
BatchExecutor:
执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch(),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDCB批处理相同。
125. mybatis 分页插件的实现原理是什么?分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
126. mybatis 如何编写一个自定义插件?转自:blog.csdn.net/qq_30051265/article/details/80266434
Mybatis自定义插件针对Mybatis四大对象(Executor,StatementHandler,ParamenterHandler,ResultSetHandler)进行拦截,具体拦截方式为:
Executor:拦截执行器的方法(log记录)StatementHandler:拦截Sql语法构建的处理ParameterHandler:拦截参数的数理ResultSetHandler:拦截结果集的处理
Mybatis自定义插件必须实现Interceptor接口:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
Intercept方法:拦截器具体处理逻辑方法plugin方法:根据签名signatureMap生成动态代理对象setProperties方法:设置Properties属性
自定义插件demo:
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation.getTarget(); //被代理对象
Method method = invocation.getMethod(); //代理方法
Object[] args = invocation.getArgs(); //方法参数
// do something ...... 方法拦截前执行代码块
Object result = invocation.proceed();
// do something .......方法拦截后执行代码块
return result;
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
一个@Intercepts可以配置多个@Signatur,@Signature中的参数定义如下:
type:表示拦截的类,这里是Executor的实现类;method:表示拦截的方法,这里是拦截Executor的update方法;args:表示方法参数。 RabbitMQ 127. rabbitmq 的使用场景有哪些?
- 跨系统的异步通信,所有需要异步交互的地方都可以使用消息队列。就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通讯方式。多个应用之间的耦合,由于消息是平台无关和语言无关的,而且语义上也不再是函数调用,因此更适合作为多个应用之间的松耦合的接口。基于消息队列的耦合,不需要发送方和接收方同时在线。在企业应用集成(EAI)中,文件传输,共享数据库,消息队列,远程过程调用都可以作为集成的方法。应用内的同步变异步,比如订单处理,就可以由前端应用将订单信息放到队列,后端应用从队列里依次获得消息处理,高峰时的大量订单可以积压在队列里慢慢处理掉。由于同步通常意味着阻塞,而大量线程的阻塞会降低计算机的性能。消息驱动的架构(EDA),系统分解为消息队列,消息制造者和消息消费者,一个处理流程可以根据需要拆成多个阶段(Stage),阶段之间用队列连接起来,前一个阶段处理的结果放入队列,后一个阶段从队列中获取消息继续处理。应用需要更灵活的耦合方式,如发布订阅,比如可以指定路由规则。跨局域网,甚至跨城市的通讯(CDN行业),比如北京机房与广州机房的应用程序的通信。
RabbitMQ中重要的角色有:生产者,消费者和代理:
生产者:消息的创建者,负责创建和推送数据到消息服务器;消费者:消息的接收方,用于处理数据和确认消息;代理:就是RabbitMQ本身,用于扮演“快递”的橘色,本身不生产消息,只是扮演“快递”的角色 129. rabbitmq 有哪些重要的组件?
ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。Channel(信道):消息推送使用的通道。Exchange(交换器):用于接受、分配消息。Queue(队列):用于存储生产者的消息。RoutiongKey(路由键):用于把生成者的数据分配到交换器上。BindingKey(绑定键):用于把交换器的消息绑定到队列上。 130. rabbitmq 中 vhost 的作用是什么?
vhost可以理解为虚拟broker,即mini-RabbitMQ server。其内部均含有独立的queue、exchange和binding等,但最最重要的是,其拥有独立的权限系统,可以做到vhost范围的用户控制。当然,从RabbitMQ的全局角度,vhost可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的vhost中)。
131. rabbitmq 的消息是怎么发送的?首先客户端必须连接到RabbitMQ 服务器才能发布和消费消息,客户端和rabbit server 之间会创建一个 tcp 连接, 一旦tcp打开并通过了认证(认证就是你发送给rabbit服务器的用户名和密码),你的客户端和RabbitMQ就创建了一条amqp信道(channel),信道是创建在“真实”tcp上的虚拟连接,amqp命令都是通过信道发送出去的,每个信道都会有一个唯一的id,不论是发布消息,订阅队列都是通过这个信道完成的。
132. rabbitmq 怎么保证消息的稳定性?提供了事务的功能。通过将channel设置为/confirm/i(确认)模式。 133. rabbitmq 怎么避免消息丢失?
- 消息持久化ACK确认机制设置集群镜像模式消息补偿机制
- 声明队列必须设置持久化 durable 设置为true。消息推送透底模式必须设置持久化,deliveryMode设置为2(持久)。消息已经到达持久化交换器。消息已经到达持久化队列。
以上四个条件都满足才能保证消息持久化成功。
135. rabbitmq 持久化有什么缺点?持久化的缺点就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。可尽量使用ssd硬盘来缓解吞吐量的问题。
136. rabbitmq 有几种广播类型? 三种广播模式:fanout:所有bind到此exchange的queue都可以接受消息(纯广播,绑定到RabbitMQ的接受者都能收到消息);direct:通过routingKey和exchange决定的那个唯一的queue可以接收消息;topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息。 137. rabbitmq 怎么实现延迟消息队列?
通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。 138. rabbitmq 集群有什么用?
集群主要有以下两个用途:
高可用:某个服务器出现问题,整个RabbitMQ还可以继续使用;高容量:集群可以承载更多的消息量。 139. rabbitmq 节点的类型有哪些?
磁盘节点:消息会存储到磁盘。内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。 140. rabbitmq 集群搭建需要注意哪些问题?
各节点之间使用“--link”连接,此属性不能忽略。各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。整个集群中必须包含一个磁盘节点。
下一篇点击这里



