面试专题(框架)

Spring

Spring有哪些特点?

 

使用Spring有什么好处?

1  应用解耦

2  依赖注入

3  AOP

4  事务管理

5  MVC

6  集成开发

 

Spring应用程序看起来像什么?

一些接口及其实现

一些POJO类

一些xml配置文件

 

Spring核心容器模块是什么?

Spring core/IOC/BeanFactory

核心容器(Spring Core)

核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。

为了降低Java开发的复杂性, Spring采取了哪几种策略

POJO/IOC/AOP/Template

基于POJO的轻量性和最小侵入性编程

通过依赖注入和面向接口实现松耦合

基于切面和惯例进行声明式编程

通过切面和模板减少样板式代码

 

谈谈Spring框架几个主要部分组成

Spring core/beans/context/aop/jdbc/tx/web mvc/orm

 

说一下Spring中支持的bean作用域

Singleton/prototype/request/session

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时该作用域才有效。

session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时该作用域才有效。

 

Spring框架中单例beans是线程安全的吗?为什么?

不是线程安全(默认singleton)

当多个线程并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对单例状态的修改(单例的成员属性),则必须考虑线程同步问题。

 

解释Spring框架中bean的生命周期

哪些是最重要的bean生命周期方法?能重写它们吗?

Setup/teardown

Xml中对应Init-method/destory-method

@PostConstruct @PreDestory

bean标签有两个重要的属性(init-method 和 destroy-method),可以通过这两个属性定义自己的初始化方法和析构方法。Spring也有相应的注解:@PostConstruct 和 @PreDestroy。

 

Spring容器实例化Bean有多少种方法?分别是什么?

使用类构造器

使用静态工厂方法

Xml配置文件factory-method

 

如何减少Spring XML的配置数量

使用Java配置文件,使xml中的bean转为Javaconfig文件方式

注解的方式

 

什么是bean自动装配?并解释自动装配的各种模式?

Spring容器可以自动配置相互协作beans之间的关联关系。这意味着Spring可以自动配置一个bean和其他协作bean之间的关系,通过检查BeanFactory 的内容里没有使用和< property>元素。

一个类就是一个Bean,Spring框架是一个Bean容器,替我们管理这些Bean,Spring就是来组织各个角色之间的关系,然后对这些角色进行调动。

自动装配:

  1. default(beans这个标签的default-autowired属性)
  2. 通过byName自动装配
  3. 通过byType自动装配
  4. 通过构造函数自动装配
  5. no不使用自动装配

 

 

自动装配有哪些好处和坏处?

自动装配的优点如下:

  1. 自动装配能显著减少装配的数量,因此在配置数量相当多时采用自动装配,可以减少工作量。
  2. 自动装配可以使配置与Java代码同步更新。例如:如果需要给一个Java类增加一个依赖,那么该依赖将自动实现而不需要修改配置。因此强烈在开发过程中采用自动装配,而在系统趋于稳定的时候改为显式装配的方式。

虽然自动装配具有上面这些优点,但不是说什么时候都可以使用它,因为它还有如下一些缺点:

  1. 尽管自动装配比显式装配更神奇,但是,Spring会尽量避免在装配不明确时进行猜测,因为装配不明确可能出现难以预料的结果,而Spring所管理的对象之间的关联关系也不再能清晰地进行文档化。
  2. 对于那些根据Spring配置文件生成文档的工具来说,自动装配将会使这些工具无法生成依赖信息。

 

是不是所有类型都能自动装配?如果不是请举例

不是。原生类型/字符串类型不可以自动装配

 

什么是循环依赖?

循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错。

public class PersonA {
	private PersonB personB;
	public PersonA(PersonB personB) {
		this.personB = personB;
	}
}
public class PersonB {
	private PersonC personC;
	public PersonB(PersonC personC) {
		this.personC = personC;
	}
}
public class PersonC {
	private PersonA personA;
	public PersonC(PersonA personA) {
		this.personA = personA;
	}
}

 

Spring如何解决循环依赖?

DefaultSingletonBeanRegistry.getSingleton源码中有3个cache:

  1. singletonFactories : 单例对象工厂的cache
  2. earlySingletonObjects :提前暴光的单例对象的Cache
  3. singletonObjects:单例对象的cache

getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取。

解析:

PersonA的setter依赖了PersonB的实例对象,同时PersonB的setter依赖了PersonA的实例对象”这种循环依赖的情况。

PersonA首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象PersonB,此时就尝试去get(PersonB),发现PersonB还没有被create,所以执行create流程,PersonB在初始化第一步的时候发现自己依赖了对象PersonA,于是尝试get(PersonA),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于PersonA通过ObjectFactory将自己提前曝光了,所以PersonB能够通过ObjectFactory.getObject拿到PersonA对象(虽然PersonA还没有初始化完全),PersonB拿到PersonA对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回PersonA中,PersonA此时能拿到PersonB的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中。而且,由于PersonB拿到了PersonA的对象引用,所以PersonB现在中的PersonA对象完成了初始化。

 

SpringMVC的工作流程和原理是什么?

 

SpringMVC与Struts2的主要区别?

区别1:

Struts2 的核心是基于一个Filter即StrutsPreparedAndExcuteFilter

SpringMvc的核心是基于一个Servlet即DispatcherServlet(前端控制器)

区别2:

Struts2是基于类开发的,传递的参数是通过类的属性传递(属性驱动和模型驱动),所以只能设计成多例prototype

SpringMvc是基于类中的方法开发的,也就是一个url对应一个方法,传递参数是传到方法的形参上面,所以既可以是单例模式也可以是多例模式singiton

区别3:

Struts2采用的是值栈存储请求以及响应数据,OGNL存取数据

SpringMvc采用request来解析请求内容,然后由其内部的getParameter给方法中形参赋值,再把后台处理过的数据通过ModelAndView对象存储,Model存储数据,View存储返回的页面,再把对象通过request传输到页面去。

 

SpringMVC的控制器是不是单例模式,如果是有什么问题,怎么解决

是。单例如果有非静态成员变量保存状态会有线程安全问题。

解决办法1:不要有成员变量,都是方法。

解决办法2:@Scope(“prototype”)

 

Spring注解的基本概念和原理

注解(Annotation),也叫元数据。一种代码级别的说明。

Spring注解分为:

1.类级别的注解:如@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named注解,都是添加在类上面的类级别注解。

Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中。

2.类内部的注解:如@Autowire、@Value、@Resource以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解。

SpringIoC容器通过Bean后置注解处理器解析Bean内部的注解。

 

举例说明什么是Spring基于Java的配置?

Spring3.0之前都是基于XML配置的,Spring3.0开始可以几乎不使用XML而使用纯粹的java代码来配置Spring应用。

@Configuration
@EnableTransactionManagement
public class AppConfig implements TransactionManagementConfigurer {
	@Bean
	public DruidDataSource dataSource() {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setUrl("jdbc:mysql://localhost:3306/sqoop");
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUsername("root");
		dataSource.setPassword("abcd_123");
		return dataSource;
	}

	@Bean
	public JdbcTemplate jdbcTemplate(DruidDataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}

	@Bean
	public PlatformTransactionManager txManager() {
		return new DataSourceTransactionManager(dataSource());
	}

	@Override
	public PlatformTransactionManager annotationDrivenTransactionManager() {
		return txManager();
	}
}

 

什么是基于注解的容器配置?

XML解耦了配置和原代码,而注解则精简了配置。spring框架基于注解的容器配置:

@Qualifier

@Autowired

@Resource

@PostContuct

@PreDestory

 

@Autowired @Resource @Inject 的区别

@Resource

1、@Resource是JSR250规范的实现,需要导入javax.annotation实现注入。

2、@Resource是根据名称进行自动装配的,一般会指定一个name属性

3、@Resource可以作用在变量、setter方法上。

@Autowired

1、@Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不同的包

2、@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性

3、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的

4、@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Name一起使用

 

什么是AOP,有什么作用,能应用在什么场景?

面向切面编程。

AOP主要作用

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

总之,面向切面的目标与面向对象的目标没有不同。一是减少重复,二是专注业务。

AOP应用场景

日志记录,性能统计,安全控制,事务处理,异常处理等问题及扩展

 

什么是织入,织入的时机是什么

把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,这样的行为叫做织入。

织入操作可以发生在如下几个阶段。

  1. 编译时:在对源代码进行编译时,特殊的编译器允许我们通过某种方式指定程序中的各个方面进行Weave的规则,并根据这些规则生成编译完成的应用程序;
  2. 编译后:根据Weave规则对已经完成编译的程序模块进行Weave操作;
  3. 载入时:在载入程序模块的时候进行Weave操作;
  4. 运行时:在程序运行时,根据情况织入程序中的对象和方面。

编译期织入是指在Java编译期,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入

 

什么是切入点,关注点,连接点

连接点(JoinPoint) spring允许你是通知(Advice)的地方,基本每个方法的前、后、环绕或抛出异常时都可以是连接点,spring只支持方法连接点。其他如AspectJ还可以让你在构造器或属性注入时都行。

切入点(Pointcut) 一个类里,有N个方法就有N个连接点,但是你并不想在所有方法上都使用通知,只想让其中几个方法执行前、后或者抛出异常完成其他功能(如日志,性能分析),那么就用切入点来筛选到那几个你想要的方法。

public class BusinessLogic {
    public void doSomething() {
        // 验证安全性;Securtity关注点
        // 执行前记录日志;Logging关注点
        doit();
        // 保存逻辑运算后的数据;Persistence关注点
        // 执行结束记录日志;Logging关注点
    }
} 

Business Logic属于核心关注点,它会调用到Security,Logging,Persistence等横切关注点。

 

Spring提供了几种AOP支持?

方式一:经典的基于代理的AOP

方式二:@AspectJ注解的切面

方式三:纯POJO切面

AOP常用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ)。

 

举例说明什么是事物以及其特点

事务是为了保证对同一数据表操作的一致性。

  1. A是原子性(atomic):事务中包含的各项操作必须全部成功执行或者全部不执行。任何一项操作失败,将导致整个事务失败,其他已经执行的任务所作的数据操作都将被撤销,只有所有的操作全部成功,整个事务才算是成功完成。     
  2. C是一致性(consistent):保证了当事务结束后,系统状态是一致的。那么什么是一致的系统状态?例如,如果银行始终遵循着"银行账号必须保持正态平衡"的原则,那么银行系统的状态就是一致的。上面的转账例子中,在取钱的过程中,账户会出现负态平衡,在事务结束之后,系统又回到一致的状态。这样,系统的状态对于客户来说,始终是一致的。     
  3. I是隔离性(isolated):使得并发执行的事务,彼此无法看到对方的中间状态。保证了并发执行的事务顺序执行,而不会导致系统状态不一致。     
  4. D是持久性(durable):保证了事务完成后所作的改动都会被持久化,即使是发生灾难性的失败。可恢复性资源保存了一份事务日志,如果资源发生故障,可以通过日志来将数据重建起来

 

Java EE事务类型有哪些?应用场景是什么?Spring是如何实现的?

一般J2EE服务器支持三种类型的事务管理。即:JDBC事务,JTA事务,容器管理事务。

JDBC事物接口:PlatformTransactionManager、AbstractPlatformTransactionManager、DataSourceTransactionManager

JTA具有三个主要的接口:UserTransaction、JTATransactionManager、Transaction接口

容器级事务主要是由容器提供的事务管理,如:WebLogic/Websphere

 

Spring有几个事物隔离级别,分别详述

事务隔离级别(5种)

DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。

未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生。

已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生。

可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生。

串行化的 (serializable) :避免以上所有读问题。

 

Mysql 默认:可重复读

Oracle 默认:读已提交

 

read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。

read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。

repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。

serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读(避免三种)。

 

描述下SpringJDBC的架构

Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发。

Spring主要提供JDBC模板方式、关系数据库对象化方式、SimpleJdbc方式、事务管理来简化JDBC编程。

support包:提供将JDBC异常转换为DAO非检查异常转换类、一些工具类如JdbcUtils等。

datasource包:提供简化访问JDBC 数据源(javax.sql.DataSource实现)工具类,并提供了一些DataSource简单实现类从而能使从这些DataSource获取的连接能自动得到Spring管理事务支持。

core包:提供JDBC模板类实现及可变部分的回调接口,还提供SimpleJdbcInsert等简单辅助类。

object包:提供关系数据库的对象表示形式,如MappingSqlQuery、SqlUpdate、SqlCall

 

描述下Spring事务处理类及其作用

Spring框架支持事务管理的核心是事务管理器抽象,对于不同的数据访问框架(如Hibernate)通过实现策略接口PlatformTransactionManager。该接口由3个方法组成:

getTransaction():返回一个已经激活的事务或创建一个新的事务(根据给定的TransactionDefinition类型参数定义的事务属性),返回的是TransactionStatus对象代表了当前事务的状态,该方法抛出TransactionException(未检查异常)表示事务由于某种原因失败。

commit():用于提交TransactionStatus参数代表的事务

rollback():用于回滚TransactionStatus参数代表的事务

 

编程式事务

1、直接使用PlatformTransactionManager实现

2、使用TransactionTemplate模板类,用于支持逻辑事务管理。

 

声明式事务

1、AOP代理方式实现

2、@Transactional实现事务管理

<tx:annotation-driven transaction-manager="transactionManager"

 

Spring提供几种事物实现?分别是什么?各有什么优缺点?

一种编程式和三种声明式

一种编程式(基于底层 API txManager.getTransaction方式或基于TransactionTemplate)

三种声明式:AOP(TransactionProxyFactoryBean),基于AspectJ的声明式事务<tx:advice>,基于注解方式的声明式事务(@Transactional)编程式事务侵入性比较强,但处理粒度更细。

 

JdbcTemplate有哪些主要方法

CRUD操作全部包含在JdbcTemplate

ResultSetExtractor/RowMapper/RowCallbackHandler

 

JdbcTemplate支持哪些回调类

1、RowMapper是一个精简版的ResultSetExtractor,RowMapper能够直接处理一条结果集内容,而ResultSetExtractor需要我们自己去ResultSet中去取结果集的内容,但是ResultSetExtractor拥有更多的控制权,在使用上可以更灵活;

2、与RowCallbackHandler相比,ResultSetExtractor是无状态的,他不能够用来处理有状态的资源。

 

MyBatis

什么是MyBatis?简述MyBatis的体系结构

Mybatis的功能架构分为三层:

  1. API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  2. 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
  3. 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

 

列举MyBatis的常用API及方法

org.apache.ibatis.session.SqlSession

MyBatis工作的主要顶层API,表示和数据库交互的会话。完毕必要数据库增删改查功能。

 

org.apache.ibatis.executor.Executor

MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护。

 

org.apache.ibatis.executor.statement.StatementHandler

封装了JDBC Statement操作。负责对JDBC statement 的操作。如设置參数、将Statement结果集转换成List集合。

 

org.apache.ibatis.executor.parameter.ParameterHandler

负责对用户传递的参数转换成JDBC Statement 所须要的参数。

 

org.apache.ibatis.executor.resultset.ResultSetHandler

负责将JDBC返回的ResultSet结果集对象转换成List类型的集合

 

org.apache.ibatis.type.TypeHandler

负责java数据类型和jdbc数据类型之间的映射和转换

 

org.apache.ibatis.mapping.MappedStatement

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

 

org.apache.ibatis.mapping.SqlSource

负责依据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回

 

org.apache.ibatis.mapping.BoundSql

表示动态生成的SQL语句以及对应的参数信息

 

org.apache.ibatis.session.Configuration

MyBatis全部的配置信息都维持在Configuration对象之中

 

对于Hibernate和MyBatis的区别与利弊,谈谈你的看法

1、hibernate真正掌握要比mybatis难,因为hibernate的功能和特性非常多,还不适合多表关联查询。

2、hibernate查询会将所有关联表的字段全部查询出来,会导致性能消耗,当然hibernate也可以自己写sql指定字段,但这就破坏了hibernate的简洁性。mybatis的sql是自己手动编写的,所以可以指定查询字段。

3、hibernate与数据库管联只需在xml文件中配置即可,所有的HQL语句都与具体使用的数据库无关,移植性很好;mybatis所有的sql都是依赖所用数据库的,所以移植性差。

4、hibernate是在jdbc上进行一次封装,mybatis是基于原生的jdbc,运行速度较快。

5、如果有上千万的表或者单次查询或提交百万数据以上不建议使用hibernate。如果统计功能、多表关联查询较多较复杂建议使用mybatis。

 

#{}和${}的区别是什么?

select * from location where id = ${id}  =>  Select * from location where id = xxx;

Select * from location where id = #{}   =>  Select * from location where id="xxxx";

${}方式无法防止sql注入;

 

Order by动态参数时,使用${}而不用#{}

模糊查询的时候使用${}

select * from location where name like '${}%';

 

Mybatis是如何进行分页的?分页插件的原理是什么?

RowBounds针对ResultSet结果集执行分页

<select id="selectById" parameterType="int" resultType="com.dongnao.demo.dao.Location">
	select * from location where id = #{id}
</select>

插件分页

@Intercepts

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

 

简述Mybatis的插件运行原理,以及如何编写一个插件

Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件。

Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法。当然,只会拦截那些你指定需要拦截的方法。

 

实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可。记住,别忘了在配置文件中配置你编写的插件。

 

Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理

Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。

Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind

 

原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。

 

动态SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据提交的查询条件进行查询。

动态SQL,即通过MyBatis提供的各种标签对条件作出判断以实现动态拼接SQL语句。

 

Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和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的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

可以。Mybatis namespace+id

 

Mybatis都有哪些Executor执行器?它们之间的区别是什么?

SimpleExecutor执行一次sql,开始创建一个statement,用完关闭statement

ReuseExector 类似数据库连接池,statement用完后返回,statement可以复用

BatchExecutor主要用于批处理执行

 

Mybatis是否可以映射Enum枚举类?

可以。Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。

 

Mybatis能否执行一对一、一对多关联查询?都有哪些实现方式,它们之间有什么区别

能,Mybatis不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询。

 

什么是MyBatis的接口绑定,有什么好处

接口映射就是在IBatis中任意定义接口,然后把接口里边的方法和SQL语句绑定,我们可以直接调用接口方法,比起SqlSession提供的方法我们可以有更加灵活的选择和设置。

 

iBatis和MyBatis在细节上的不同有哪些

区别太多,篇幅太长,大家可以自行百度下。

 

讲下MyBatis的缓存

MyBatis 提供了查询缓存来缓存数据,以提高查询的性能。MyBatis 的缓存分为一级缓存和二级缓存。

 

一级缓存是 SqlSession 级别的缓存

二级缓存是 mapper 级别的缓存,多个 SqlSession 共享

一级缓存

一级缓存是SqlSession级别的缓存,是基于HashMap的本地缓存。不同的 SqlSession之间的缓存数据区域互不影响。

 

一级缓存的作用域是SqlSession范围,当同一个SqlSession执行两次相同的 sql语句时,第一次执行完后会将数据库中查询的数据写到缓存,第二次查询时直接从缓存获取不用去数据库查询。当SqlSession执行insert、update、delete 操做并提交到数据库时,会清空缓存,保证缓存中的信息是最新的。

 

MyBatis默认开启一级缓存。

 

二级缓存

二级缓存是mapper级别的缓存,同样是基于HashMap进行存储,多个SqlSession可以共用二级缓存,其作用域是mapper的同一个namespace。不同的SqlSession两次执行相同的namespace下的sql语句,会执行相同的sql,第二次查询只会查询第一次查询时读取数据库后写到缓存的数据,不会再去数据库查询。

 

MyBatis 默认没有开启二级缓存,开启只需在配置文件中写入如下代码:

<settings>  
    <setting name="cacheEnabled" value="true"/>  
</settings>

 

 

 

 

猜你喜欢

转载自my.oschina.net/u/3728166/blog/2878954
今日推荐