InterV 3:流行框架与技术


一、 Spring

1) Spring有哪些特点?

应用解耦,简化开发(注解),IOC,AOP,事物管理

2) 使用Spring有什么好处?

1  应用解耦

2  依赖注入

3  AOP

4  事务管理

5  MVC

6  集成开发

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

一些接口及其实现

一些POJO类

一些xml配置文件

4) Spring核心容器模块是什么?

Spring core/IOC/BeanFactory

核心容器(Spring Core)

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

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

POJO/IOC/AOP/Template

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

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

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

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

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

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

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

Singleton/prototype/request/session

Scope=”singleton/prototype/request/session”,默认是singleton

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时该作用域才有效。

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

不是线程安全(默认singleton)

当多个线程同时修改单例的属性时必须考虑线程同步问题。

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

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

Setup/teardown

Xml中对应:init-method/destory-method

注解对应:@PostConstruct @PreDestory

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

析构函数的作用是回收内存和资源,通常用于释放在构造函数或对象生命期内获取的资源。

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

new 构造方法

Person p = new Person();

工厂方法

静态的

public class PersonFactory {
    public static Person getPerson() {
        return new Person();
    }
}

成员方法

public class PersonFactory {
    public Person getPerson() {
        return new Person();
    }
}

Xml配置文件factory-method

12) 如何减少Spring XML的配置数量

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

注解的方式

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

什么是bean自动装配:

在spring中,对象无需自己查找或创建与其关联的其他对象,容器负责把需要相互协作的对象引用赋予各个对象。

自动装配的各种模式:

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

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

自动装配的优点:

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

自动装配的缺点:

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

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

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

16) 什么是循环依赖?

循环依赖就是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;
    }
}

17) Spring如何解决循环依赖?

使用set方法解决循环依赖

原理是使用了Spring的3级缓存

DefaultSingletonBeanRegistry.getSingleton源码中有3个cache:

singletonObjects:单例对象的cache   一级缓存

earlySingletonObjects :提前暴光的单例对象的Cache  二级缓存

singletonFactories : 单例对象工厂的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对象完成了初始化。

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

用户请求首先发送到前端控制器DispatcherServlet,DispatcherServlet根据请求的信息来决定使用哪个页面控制器Controller(也就是我们通常编写的Controller)来处理该请求。找到控制器之后,DispatcherServlet将请求委托给控制器去处理。

接下来控制器开始处理用户请求,控制器会根据请求信息进行处理,调用业务层等等,处理完成之后,会把结果封装成一个ModelAndView返回给DispatcherServlet。

DispatcherServlet接到控制器的返回结果后,根据返回的视图名选择相应的视图模板(ViewReslover),并根据返回的数据进行渲染。

最后DispatcherServlet将结果返回给用户。

19) 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传输到页面去。

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

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

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

解决办法2:将控制器设置为多例的 @Scope(“prototype”)

21) Spring注解的基本概念和原理

注解(Annotation),也叫元数据。一种代码级别的说明。原理是通过反射实现的

Spring注解分为:

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

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

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

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

22) 举例说明什么是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();
    }
}

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

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

@Qualifier

@Autowired

@Resource

@PostContuct

@PreDestory

24) @Autowired @Resource @Inject 的区别

@Resource

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

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

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

@Autowired和@Inject

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

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

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

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

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

什么是AOP:

面向切面编程。

AOP主要作用:

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

总结:使用AOP不会改变和影响业务逻辑代码。

一是减少重复,二是专注业务。

AOP应用场景:

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

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

什么是织入:

将用户提供的增强功能加到指定的方法上叫做织入

织入的时机是什么:

创建bean实例的时候进行织入,在bean初始化完成后,进行织入

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

我们先来看一下下面的这张图

说明:

程序运行时会调用很多方法,调用的很多方法就叫做Join points(连接点,可以被选择来进行增强的方法点),在方法的前或者后选择一个地方来切入,切入的的地方就叫做Pointcut(切入点,选择增强的方法),然后把要增强的功能(Advice)加入到切入点所在的位置。Advice和Pointcut组成一个切面(Aspect)

AOP的几个概念:

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

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

28) Spring提供了几种AOP支持?

方式一:经典的基于代理的AOP(JDK动态代理、Cglib)

方式二:@AspectJ注解的切面

方式三:纯POJO切面

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

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

什么是事物:

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

事物的特点:

ACID

A是原子性(atomic):事务中包含的各项操作必须全部成功执行或者全部不执行。任何一项操作失败,将导致整个事务失败,其他已经执行的任务所作的数据操作都将被撤销,只有所有的操作全部成功,整个事务才算是成功完成。     

C是一致性(consistent):保证了当事务结束后,系统状态是一致的。那么什么是一致的系统状态?例如,如果银行始终遵循着"银行账号必须保持正态平衡"的原则,那么银行系统的状态就是一致的。上面的转账例子中,在取钱的过程中,账户会出现负态平衡,在事务结束之后,系统又回到一致的状态。这样,系统的状态对于客户来说,始终是一致的。     

I是隔离性(isolated):并发执行的事务,彼此无法看到对方的中间状态。保证了并发执行的事务顺序执行,而不会导致系统状态不一致。     

D是持久性(durable):保证了事务完成后所作的改动都会被持久化,即使是发生灾难性的失败。可恢复性资源保存了一份事务日志,如果资源发生故障,可以通过日志来将数据重建起来

30) Java EE事务类型有哪些?应用场景是什么?Spring是如何实现的?(没回答完)

 Java EE事务类型:

JDBC事务,JTA事务,容器管理事务。

JDBC事物接口:PlatformTransactionManager、AbstractPlatformTransactionManager、DataSourceTransactionManager

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

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

应用场景:

JDBC事务:针对单库

JTA事务:分布式事物,针对多库,可以使用MQ来实现

容器管理事务:

Spring是如何实现的:

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

事务隔离级别(5种)

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

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

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

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

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

Mysql 默认:可重复读

Oracle 默认:读已提交

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

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

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

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

 

32) 描述下SpringJDBC的架构

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

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

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

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

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

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

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

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

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

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

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

编程式事务:在分布式事务里面用的最多

1、直接使用PlatformTransactionManager实现

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

声明式事务

1、AOP代理方式实现

2、@Transactional实现事务管理

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

一种编程式和三种声明式

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

三种声明式:AOP(TransactionProxyFactoryBean),基于AspectJ的声明式事务,基于注解方式的声明式事务(@Transactional)

编程式事务侵入性比较强,但处理粒度更细。

35) JdbcTemplate有哪些主要方法

CRUD操作全部包含在JdbcTemplate

ResultSetExtractor/RowMapper/RowCallbackHandler

36) JdbcTemplate支持哪些回调类

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

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

 二、MyBatis

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

什么是MyBatis:

一个半自动化的orm框架(Object Relation Mapping)。支持普通sql查询,存储过程和高级映射的优秀的、轻量级的持久层框架

为什么称为半自动化?:

关系型数据库的操作是通过SQL语句来完成的,Mybatis在帮我们做对象的存取时,需要我们提供对应的SQL语句,它不自动帮我们生成SQL语句,而只帮我们完成:

1)对象属性到SQL语句参数的自动填充;
2)SQL语句执行结果集到对象的自动提取;
所以称为半自动的。而我们了解的另一个ORM框架Hibernate则是全自动的。

MyBatis的体系结构:

Mybatis的功能架构分为三层:

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

2) 列举MyBatis的常用API及方法

2.1 org.apache.ibatis.session.SqlSession

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

2.2 org.apache.ibatis.executor.Executor

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

 2.3 org.apache.ibatis.executor.statement.StatementHandler

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

 2.4 org.apache.ibatis.executor.parameter.ParameterHandler

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

 2.5 org.apache.ibatis.executor.resultset.ResultSetHandler

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

 2.6 org.apache.ibatis.type.TypeHandler

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

2.7 org.apache.ibatis.mapping.MappedStatement

MappedStatement维护了一条节点的封装

2.8 org.apache.ibatis.mapping.SqlSource

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

 2.9 org.apache.ibatis.mapping.BoundSql

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

 2.10 org.apache.ibatis.session.Configuration

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

3) 对于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。

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

#{}:Mybatis预编译

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

${}:替换

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

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

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

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

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

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

Mybatis是如何进行分页的:

1. RowBounds针对ResultSet结果集执行分页

2. Limit方式分页

分页插件的原理是什么:

@Intercepts

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

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

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

Mybatis的插件运行原理:

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

如何编写一个插件:

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

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

Mybatis动态sql是做什么的:

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

都有哪些动态sql:

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

动态sql的执行原理:

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

 动态sql解决的问题:

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

8) 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()方法的调用。这就是延迟加载的基本原理。

9) Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

可以。Mybatis namespace+id

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

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

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

BatchExecutor主要用于批处理执行

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

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

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

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

13)MyBatis实现一对一有几种方式?具体怎么操作的

有联合查询和嵌套查询

联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置

14)MyBatis实现一对多有几种方式,怎么操作的

有联合查询和嵌套查询

联合查询是几个表联合查询,只查询一次,通过在resultMap里面配置collection节点配置一对多的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置

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

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

16)接口绑定有几种实现方式,分别是怎么实现的?

接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select@Update等注解里面包含Sql语句来绑定,

另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名.

17)什么情况下用注解绑定,什么情况下用xml绑定?

Sql语句比较简单时候,用注解绑定,

SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多

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

1、Mybatis实现了接口绑定,使用更加方便。 
在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 
而Mybatis实现了DAO接口与xml映射文件的绑定,自动为我们生成接口的具体实现,使用起来变得更加省事和方便。 
这可以说是Mybatis最重要的改进。 

2、MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。 
熟悉struts2的人应该对OGNL表达式不会感到陌生, 
MyBatis采用OGNL表达式简化了配置文件的复杂性,使用起来更简洁。 

3. IBatis里面的核心处理类叫做SqlMapClient, MyBatis里面的核心处理类叫做SqlSession

4. ibatis中根元素是sqlMap,mybatis中是mapper;

5. 在 iBatis 中,namespace 不是必需的,且它的存在没有实际的意义。在 MyBatis 中,namespace 终于派上用场了,它使得映射文件与接口绑定变得非常自然。

6. ibatis中有resultMap和resultClass两种返回类型,resultMap是我们在ibatis的配置文件中定义的,也就是在配置文件中使用resultMap元素定义的;resultClass是指java语言中内置的类型,如:integer、java.util.HashMap等等;

mybatis中将两者统一为resultType,这样挺好的,开发者不用再记两个属性了。

7. ibatis中有parameterClass,mybatis中有parameterType,两者区别不大。

19) 讲下MyBatis的缓存

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

一级缓存:

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

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

MyBatis默认开启一级缓存。

二级缓存:

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

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

 

      

20)MyBatis的好处是什么

1. Mybatis把sql语句从Java源程序中独立出来, 放在单独的XML文件中编写,给程序的维护带来了很大便利。

2. Mybatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象, 大大简化了Java数据库编程的重复工作。

3. Mybatis可以灵活控制sql语句, 因此能够实现比hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。

4. Mybatis实现了接口绑定,使用更加方便。 
在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 
而Mybatis实现了DAO接口与xml映射文件的绑定,自动为我们生成接口的具体实现,使用起来变得更加省事和方便。 
这可以说是Mybatis最重要的改进。