面试题整理3(如有错误欢迎指导)

1、谈谈你对Struts的理解。

答:

  1. mvc设计模式的web层框架。本质是servlet,ActionServlet或者ActionServlet的子类。通过web.xml配置符合条件的请求交给servlet处理,参照配置文件将请求分发个action。
  2. 提交给action之前或封装成formBean对象,每个属性对应一个请求参数。并且会通过formBean中的validate方法进行校验,校验通过提交给action的execute该方法,否则返回错误页面,有input属性指定。
  3. action执行结束返回试图,视图用actionForward对象来表示,actionForward通过struts-config.xml来关联jsp页面。因为程序中使用的是在struts-config.xml配置文件为jsp页面设置的逻辑名,这样可以实现action程序代码与返回的jsp页面名称的解耦。

2、谈谈你对Hibernate的理解。

答:

  1. hibernate运行原理:
    hibernate里面提供了3个核心接口
    Configuration、SessionFactory、Session
    1、hibernate启动的时候利用Configuration读取xml配置文件
    2、通过配置文件创建SessionFactory对象,初始化hibernate基本信息
    3、获取session然后调用CRUD方法进行数据操作,hibernate会把我们的数据进行三种状态的划分,然后根据状态进行管理我们的数据,对应的发送SQL进行数据操作
    4、关闭session,如果有事务的情况下,需要手动获取事务并开启,然后事务结束后提交事务。
    5、在提交事务的时候,去验证我们的快照里面的数据和缓存数据是否一致,如果不一致,发送SQL进行修改
  2. hibernate的get方法和load方法的区别
    1、get和load都是利用主键策略查询数据,
    2、get默认不使用懒加载机制,load默认要使用懒加载机制,所谓的懒加载就是我们这个数据如果不使用,hibernate就不发送SQL到数据库查询数据。
    3、当查询数据库不存在的数据的时候,get方法返回null,load方法抛出空指针异常,原因是因为,load方法采用的动态代理的方式实现的,我们使用load方法的时候,hibernate会创建一个该实体的代理对象,该代理只保存了该对象的ID,当我们访问该实体对象其他属性,hibernate就发送SQL查询数据封装到代理对象,然后在利用代理对象返回给我们实际的数据.
    PS:延迟加载,也叫懒加载,它是hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。因为是代理对象所以不能用 == null 来判断,因为代理对象不是null;
  3. hibernate的数据三种状态
    瞬时的(刚new出来的数据–内存有,数据库没有)
    持久的 (从数据查询的,或者刚保存到数据库,session没关闭的, 数据库有,内存也有)
    游离的 、脱管的(数据库有,内存没有)
    PS:能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。

3、谈谈你对Spring的理解。

答:

  1. Spring是实现了工厂模式的工厂类(在这里有必要解释清楚什么是工厂模式),这个类名为BeanFactory(实际上是一个接口),在程序中通常BeanFactory的子类ApplicationContext。Spring相当于一个大的工厂类,在其配置文件中通过元素配置用于创建实例对象的类名和实例对象的属性。
  2. Spring提供了对IOC良好支持,IOC是一种编程思想,是一种架构艺术,利用这种思想可以很好地实现模块之间的解耦,IOC也称为DI(Depency Injection),
    PS:IOD(控制反转)/DI(依赖注入)依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。例:比如以前演员都是自己找活来升级,现在接入了中介公司,演员投递给中介公司,然后回家等待,中介公司来管理工作的分配。
  3. Spring提供了对AOP技术的良好封装, AOP称为面向切面编程,就是系统中有很多各不相干的类的方法,在这些众多方法中要加入某种系统功能的代码,例如,加入日志,加入权限判断,加入异常处理,这种应用称为AOP。
    PS:aop主要是通过动态代理来实现的。动态代理有两种方式:一java动态代理技术,这种方式要求类必须有接口(Interface)。二使用CGLib只要业务类没有final修饰即可;

4、谈谈Struts的优缺点。

答:

  1. 优点
    1.、实现MVC模式,结构清晰,使开发者只关注业务逻辑的实现.
    2、有丰富的tag可以用 ,Struts的标记库(Taglib),如能灵活动用,则能大大提高开发效率
    3.、页面导航使系统的脉络更加清晰。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时,这种优势体现得更加明显。
    4.、提供Exception处理机制 .
    5.、数据库链接池管理
  2. 缺点
    1、转到展示层时,需要配置forward,如果有十个展示层的jsp,需要配置十次struts,而且还不包括有时候目录、文件变更,需要重新修改forward,注意,每次修改配置之后,要求重新部署整个项目,而tomcate这样的服务器,还必须重新启动服务器
    2、对事件支持不够.在struts中,实际是一个表单Form对应一个Action类(或DispatchAction),换一句话说:在Struts中实际是一个表单只能对应一个事件,struts这种事件方式称为application event,application event和component event相比是一种粗粒度的事件
    PS: 这里总结的比较少,欢迎补充,不过struts基本除了老项目很少使用了。

5、MyBatis与Hibernate有什么不同?

答:iBatis即MyBatis(2.0版本改名为MyBatis);

  1. Hibernate的优缺点:
    **优点:**面向对象开发,不需要自己写sql语句。如果进行数据库迁移不需要修改sql语句,只需要修改一下方言。
    **缺点:**hibernate维护数据表关系比较复杂。完全是有hibernate来管理数据表的关系,对于我们来说完全是透明的,不易维护。
    Hibernate自动生成sql语句,生成sql语句比较复杂,比较难挑错。
    Hibernate由于是面向对象开发,不能开发比较复杂的业务。
    应用场景:
    适合需求变化较少的项目,比如ERP,CRM等等
    Mybatis框架对jdbc框架进行封装,屏蔽了jdbc的缺点,开发简单。
    Mybatis只需要程序员关注sql本身,不需要过多的关注业务。对sql的优化,修改比较容易
    适应场景:
    适合需求变化多端的项目,比如:互联网项目
  2. mybatis与hibernate重要区别
    企业开发进行技术选型 ,考虑mybatis与hibernate适用场景。
    mybatis:入门简单,程序容易上手开发,节省开发成本 。mybatis需要程序员自己编写sql语句,是一个不完全 的ORM框架,对sql修改和优化非常容易实现 。
    mybatis适合开发需求变更频繁的系统,比如:互联网项目。
    hibernate:入门门槛高,如果用hibernate写出高性能的程序不容易实现。hibernate不用写sql语句,是一个 ORM框架。
    hibernate适合需求固定,对象数据模型稳定,中小型项目,比如:企业OA系统
    PS: 个人更喜欢MyBatis.

6、在hibernate进行多表查询每个表中各取几个字段,也就是说查询出来的结果集没有一个实体类与之对应如何解决?

答:

  1. 按照Object[]数据取出数据,然后自己组bean。
  2. 对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1filed1,type2field2) ,然后在hql里面就可以直接生成这个bean了。

7、 介绍一下Hibernate的二级缓存。

答:

  1. 什么是缓存: 缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似HashMap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。
  2. 一级缓存是什么?为什么要有二级缓存?: Hibernate的Session就是一种缓存,我们通常将之称为Hibernate的一级缓存,当想使用session从数据库中查询出一个对象时,Session也是先从自己内部查看是否存在这个对象,存在则直接返回,不存在才去访问数据库,并将查询的结果保存在自己内部。由于Session代表一次会话过程,一个Session与一个数据库连接相关连,所以Session最好不要长时间保持打开,通常仅用于一个事务当中,在事务结束时就应关闭。并且Session是线程不安全的,被多个线程共享时容易出现问题。Hibernate的二级缓存就是要为Hibernate配置一种全局缓存,让多个线程和多个事务都可以共享这个缓存。我们希望的是一个人使用过,其他人也可以使用,session没有这种效果。
    PS: 在一级缓存,二级缓存和查询缓存都打开的情况下作查询操作时这样的:查询普通属性,会先到查询缓存中取,如果没有,则查询数据库;查询实体,会先到查询缓存中取id,如果有,则根据id到缓存(一级/二级)中取实体,如果缓存中取不到实体,再查询数据库。

8、Hibernate的一对多和多对一双向关联的区别?

答: 一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同。
它们的区别在于维护的关系不同:
一对多关联映射是指在加载一的一端数据的同时加载多的一端的数据多对一关联映射是指在加载多的一端数据的同时加载一的一端的数据。

9、使用Spring框架的好处是什么?

答:

  1. 轻量: Spring 是轻量的,基本的版本大约2MB。
  2. 控制反转: Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
  3. 面向切面的编程(AOP): Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
  4. 容器: Spring 包含并管理应用中对象的生命周期和配置。
  5. MVC框架: Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
  6. 事务管理: Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
  7. 异常处理: Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

10、 ApplicationContext通常的实现是什么?

答:

  1. FileSystemXmlApplicationContext : 此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
  2. ClassPathXmlApplicationContext: 此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
  3. WebXmlApplicationContext: 此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。

11、什么是Spring的依赖注入?有哪些方法进行依赖注入?

答:

  1. 详情见上边3题
  2. 三种依赖方式:
    构造器注入
    将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。
    优点:
    对象初始化完成后便可获得可使用的对象。
    缺点:
    当需要注入的对象很多时,构造器参数列表将会很长;
    不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。
    setter方法注入
    IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。
    优点:
    灵活。可以选择性地注入需要的对象。
    缺点:
    依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。
    接口注入
    依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。
    优点
    接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。
    缺点:
    侵入行太强,不建议使用。
    **PS:**什么是侵入行?
    如果类A要使用别人提供的一个功能,若为了使用这功能,需要在自己的类中增加额外的代码,这就是侵入性。

12、什么是Spring beans?

答:
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中 的形式定义。 Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为TRUE,bean 就是单件,否则就是一个 prototype bean。默认是TRUE,所以所有在Spring框架中的beans 缺省都是单件。

13、解释Spring支持的几种bean的作用域。

答:

  1. singleton : bean在每个Spring ioc 容器中只有一个实例。
  2. prototype: 一个bean的定义可以有多个实例。
  3. request: 每次http请求都会创建一个bean,该作用域仅在基于web的 Spring ApplicationContext情形下有效。
  4. session: 在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  5. global-session: 在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

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

答:

  1. Spring容器 从XML 文件中读取bean的定义,并实例化bean。
  2. Spring根据bean的定义填充所有的属性。
  3. 如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
  4. 如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
  5. 如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
  6. 如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
  7. 如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
  8. 如果bean实现了 DisposableBean,它将调用destroy()方法。

15、在 Spring中如何注入一个java集合?

答:

  1. 类型用于注入一列值,允许有相同的值。
  2. 类型用于注入一组值,不允许有相同的值。
  3. 类型用于注入一组键值对,键和值都可以为任意类型。
  4. 类型用于注入一组键值对,键和值都只能为String类型。

16、解释不同方式的自动装配 。

答:

  1. no: 默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
  2. byName: 通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
  3. byType:: 通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
  4. constructor: 这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  5. autodetect: 首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

17、Spring框架的事务管理有哪些优点?

答:
Spring 提供两种事务:
编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码
声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。
优点: 它为不同的事务API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式。它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API。 它和Spring各种数据访问抽象层很好得集成。

18、举例spring常用的注解。

答:

  1. @Component 组件,没有明确的角色
  2. @Service 在业务逻辑层使用(service层)
  3. @Repository 在数据访问层使用(dao层)
  4. @Controller 在展现层使用,控制器的声明(C)
  5. @Aspect 声明一个切面(类上) 使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
  6. @After 在方法执行之后执行(方法上) @Before 在方法执行之前执行(方法上) @Around 在方法执行之前与之后执行(方法上)
  7. @PointCut 声明切点 在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)

19、什么是ORM?

答: 对象关系映射(Object-Relational Mapping,简称ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另外一种形式。

20、Hibernate中SessionFactory是线程安全的吗?Session是线程安全的吗(两个线程能够共享同一个Session吗)?

答:

  1. SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory一般只会在启动的时候构建。对于应用程序,最好将SessionFactory通过单例模式进行封装以便于访问。
  2. Session是一个轻量级非线程安全的对象,线程间不能共享session。它表示与数据库进行交互的一个工作单元。Session是由SessionFactory创建的,在任务完成之后它会被关闭。Session是持久层服务对外提供的主要接口。

21、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?

答: Hibernate的对象有三种状态:瞬时态(transient)、持久态(persistent)和游离态(detached)。

  1. 瞬时态 的实例可以通过调用save()、persist()或者saveOrUpdate()方法变成持久态;
  2. 游离态 的实例可以通过调用 update()、saveOrUpdate()、lock()或者replicate()变成持久态。save()和persist()将会引发SQL的INSERT语句,而update()或merge()会引发UPDATE语句。
  3. save()、update()的区别是一个改变瞬时态,一个改变游离态,最终目标是编程持久态。
  4. merge()方法可以完成save()和update()方法的功能,它的意图是将新的状态合并到已有的持久化对象上或创建新的持久化对象。
  5. persist()方法,按照官方文档的说明:
    1、persist()方法把一个瞬时态的实例持久化,但是并不保证标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时间;
    2、persist()方法保证当它在一个事务外部被调用的时候并不触发一个INSERT语句,当需要封装一个长会话流程的时候,persist()方法是很有必要的;
    3、save()方法不保证第2条,它要返回标识符,所以它会立即执行INSERT语句,不管是在事务内部还是外部。至于lock()方法和update()方法的区别,update()方法是把一个已经更改过的脱管状态的对象变成持久状态;lock()方法是把一个没有更改过的脱管状态的对象变成持久状态。

22、阐述Session加载实体对象的过程。

答:

  1. Session在调用数据库查询功能之前,首先会在一级缓存中通过实体类型和主键进行查找,如果一级缓存查找命中且数据状态合法,则直接返回;
  2. 如果一级缓存没有命中,接下来Session会在当前NonExists记录(相当于一个查询黑名单,如果出现重复的无效查询可以迅速做出判断,从而提升性能)中进行查找,如果NonExists中存在同样的查询条件,则返回null;
  3. 如果一级缓存查询失败查询二级缓存,如果二级缓存命中直接返回;
  4. 如果之前的查询都未命中,则发出SQL语句,如果查询未发现对应记录则将此次查询添加到Session的NonExists中加以记录,并返回null;
  5. 如果命中根据配置和sql返回得到ResultSet,创建对象。
  6. 将对象存入session,如果有拦截器执行拦截器onLoad方法
  7. 如果设置了二级缓存存入二级缓存,返回数据。

23、MyBatis中使用#和$书写占位符有什么区别?

答:

  1. #把变量转化成字符串,可以有效防止sql注入问题
  2. $ 是原样输入,有可能引发失去了注入问题
    PS: order by子句的时候应该用$而不是#。
    SQL注入 (SQLi)是一种注入攻击,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录。
    SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQL Server或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。

24、解释一下MyBatis中命名空间(namespace)的作用。

答:

  1. 在大型项目中,可能存在大量的SQL语句,这时候为每个SQL语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在MyBatis中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个SQL语句就成了定义在这个命名空间中的一个ID。只要我们能够保证每个命名空间中这个ID是唯一的,即使在不同映射文件中的语句ID相同,也不会再产生冲突了。

25、MyBatis中的动态SQL是什么意思?

答: 对于一些复杂的查询,我们可能会指定多个查询条件,但是这些条件可能存在也可能不存在,如果不使用持久层框架我们可能需要自己拼装SQL语句,不过MyBatis提供了动态SQL的功能来解决这个问题。
PS: MyBatis中用于实现动态SQL的元素主要有: - if - choose / when / otherwise - trim - where - set - foreach

26、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?

答:

  1. JDBC:数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
    MyBatis:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
  2. JDBC:Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
    MyBatis:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
  3. JDBC:向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    MyBatis: Mybatis自动将java对象映射至sql语句。
  4. JDBC:对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
    MyBatis:Mybatis自动将sql执行结果映射至java对象。

27、简单的说一下MyBatis的一级缓存和二级缓存?

答:
Mybatis首先去缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象,Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值