面试题(2)——struts2,hibernate,spring

文章目录

1 Struts2

1、客户端浏览器发出HTTP请求。
2、根据web.xml配置,该请求被FilterDispatcher接收。
3、根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Aciton。
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面。
6、返回HTTP响应到客户端浏览器。

1.Struts2 的六个基本包

struts2-core-2.1.6.jar :开发的核心类库
freemarker-2.3.13.jar :struts2 的 UI 标签的模板使用 freemarker 编写
commons-logging-1.0.4.jar :日志包
ognl-2.6.11.jar :对象图导航语言,通过它来读写对象属性
xwork-2.1.2.jar :xwork 类库,struts2 在其上进行构建
commons-fileupload-1.2.1.jar:文件上传组件,2.1.6 版本后必须加入此 jar 包

2.struts2 配置文件

(1).web.xml 文件 主要完成对 StrutsPrepareAndExecuteFilter 的配置(在以前的版本中是对 FilterDispatcher 配置,新版本同样支持用 FilterDispatcher 配置),它的实质是一个过滤器,它负责初始化整个 Struts 框架并且处理所有的请求。这个过滤器可以包括一些初始化参数,有的参数指定了要加载哪些额外的 xml 配置文件,还有的会影响 struts 框架的行为。除了 StrutsPrepareAndExecuteFilter 外,Struts 还提供了一个 ActionContexCleanUp 类,它的主要任务是当有其它一些过滤器要访问一个初始化好了的 struts 框架的时候,负责处理一些特殊的清除任务。
(2).struts.xml 文件 框架的核心配置文件就是这个默认的 struts.xml 文件,在这个默认的配置文件里面我们可以根据需要再包括其它一些配置文件。在通常的应用开发中,我们可能想为每个不同的模块单独配置一个 struts.xml 文件,这样也利于管理和维护。这也是我们要配置的主要文件。
(3).struts.properties(参 default.properties) 在 Struts 框架使用了很多属性,我们可以通过改变这些属性来满足我们的需求。要改变这些属性,只需在 struts.properties 文件中指定属性的 key 和 value 即可。属性文件可以放在任何一个包含在 classpath 中的路径上,但是通常我们都把它放在/WEB-INF/classes 目录下面。我们可以在 struts-default.properties 文件中找到一个属性的列表。
(4)struts-default.xml 此文件是 struts2 框架默认加载的配置文件,它定义了 struts2 一些核心 bean 和拦截器,它会自动包含(included)到 struts.xml 文件中(实质是通过< package extends=“struts-default”>),并为我们提供了一些标准的配置。我们可以在 struts2-core.jar中找到这个文件。

3.Struts2 常用注解

@ParentPackage:定父包
@Namespace:指定命名空间
@Results:一组结果的数组
@Result(name=“success”,location="/msg.jsp"): 一个结果的映射(注意没有 s)
@Action(value=“login”):指定某个请求处理方法的请求 URL。注意,它不能添加在 Action 类
上,要添加到方法上。
@ExceptionMappings :一级声明异常的数组
@ExceptionMapping: 映射一个声明异常自定义注解拦截器权限控制

4.struts2 工作流程?你的理解?

Struts 2 框架本身大致可以分为 3 个部分:
核心控制器 FilterDispatcher、业务控制器 Action 和用户实现的企业业务逻辑组件。
核心控制器 FilterDispatcher 是 Struts 2 框架的基础,包含了框架内部的控制流程和处理机制。业务控制器 Action 和业务逻辑组件是需要用户来自己实现的。
用户在开发 Action 和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher 来使用。
Struts 2 的工作流程相对于 Struts 1 要简单,与 WebWork 框架基本相同,所以说 Struts 2 是 WebWork 的升级版本。基本简要流程如下:
1 、客户端初始化一个指向 Servlet 容器的请求;
2、 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做 ActionContextCleanUp 的可选过滤器,这个过滤器对于 Struts2 和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3 、接着 FilterDispatcher 被调用,FilterDispatcher 询问 ActionMapper 来决定这个请是否需要调用某个 Action;
4、如果 ActionMapper 决定需要调用某个 Action,FilterDispatcher 把请求的处理交给 ActionProxy
5、ActionProxy 通过 Configuration Manager 询问框架的配置文件,找到需要调用的 Action 类;
6、ActionProxy 创建一个 ActionInvocation 的实例;
7、ActionInvocation 实例使用命名模式来调用,在调用 Action 的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦 Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回
结果。返回结果通常是(但不总是,也可 能是另外的一个 Action 链)一个需要被表示的
JSP 或者 FreeMarker 的模版。在表示的过程中可以使用 Struts2 框架中继承的标签。在这个过程中需要涉及到 ActionMapper
9、响应的返回是通过我们在 web.xml 中配置的过滤器
10、如果 ActionContextCleanUp 是当前使用的,则 FilterDispatecher 将不会清理 sreadlocal ActionContext;
如果 ActionContextCleanUp 不使用,则将会去清理 sreadlocals。

理解:

  1. struts是一个按MVC模式设计的Web层框架,其实它就是一个Servlet,这个Servlet名为ActionServlet,或是ActionServlet的子类。我们可以在web.xml文件中将符合某种特征的所有请求交给这个Servlet处理,这个Servlet再参照一个配置文件将各个请求分别分配给不同的action去处理。
    (struts的配置文件可以有多个,可以按模块配置各自的配置文件,这样可以防止配置文件的过度膨胀)
  2. ActionServlet把请求交给action去处理之前,会将请求参数封装成一个formbean对象(就是一个java类,这个类中的每个属性对应一个请求参数),
  3. 要说明的是, ActionServlet把formbean对象传递给action的execute方法之前,可能会调用formbean的validate方法进行校验,只有校验通过后才将这个formbean对象传递给action的execute方法,否则,它将返回一个错误页面,这个错误页面由input属性指定。
  4. action执行完后要返回显示的结果视图,这个结果视图是用一个ActionForward对象来表示的,actionForward对象通过struts-config.xml配置文件中的配置关联到某个jsp页面,因为程序中使用的是在struts-config.xml配置文件为jsp页面设置的逻辑名,这样可以实现action程序代码与返回的jsp页面名称的解耦。
5.Struts2 问题合集
5.1Struts 的设计模式

MVC 模式: web 应用程序启动时就会加载并初始化 ActionServler。用户提交表单时,一个配置好的 ActionForm 对象被创建,并被填入表单相应的数据,ActionServler 根据 Strutsconfig.xml 文件配置好的设置决定是否需要表单验证,如果需要就调用 ActionForm 的Validate()验证后选择将请求发送到哪个 Action,如果 Action 不存在,ActionServlet 会先创建这个对象,然后调用 Action 的 execute()方法。Execute()从 ActionForm 对象中获取数据,完成业务逻辑,返回一个 ActionForward 对象,ActionServlet 再把客户请求转发给 ActionForward 对象指定的 jsp 组件,ActionForward 对象指定的 jsp 生成动态的网页,返回给客户。

5.2 拦截器和过滤器的区别

1、拦截器是基于 java 反射机制的,而过滤器是基于函数回调的。
2、拦截器不依赖于 servlet 容器,过滤器依赖于 servlet 容器。
3、拦截器只能对 Action 请求起作用,而过滤器则可以对几乎所有请求起作用。
4、拦截器可以访问 Action 上下文、值栈里的对象,而过滤器不能。
5、在 Action 的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

5.3 struts2 有哪些优点?

1)在软件设计上 Struts2 的应用可以不依赖于 Servlet API 和 struts API。Struts2 的这种设计属于无侵入式设计;
2)拦截器,实现如参数拦截注入等功能;
3)类型转换器,可以把特殊的请求参数转换成需要的类型;
4)多种表现层技术,如:JSP、freeMarker、Velocity 等;
5)Struts2 的输入校验可以对指定某个方法进行校验;
6)提供了全局范围、包范围和 Action 范围的国际化资源文件管理实现

优点:

  1. 实现MVC模式,结构清晰,使开发者只关注业务逻辑的实现.
  2. 有丰富的tag可以用 ,Struts的标记库(Taglib),如能灵活动用,则能大大提高开发效率
  3. 页面导航使系统的脉络更加清晰。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时,这种优势体现得更加明显。
  4. 提供Exception处理机制 .
  5. 数据库链接池管理
  6. 支持I18N

缺点:

  1. 转到展示层时,需要配置forward,如果有十个展示层的jsp,需要配置十次struts,而且还不包括有时候目录、文件变更,需要重新修改forward,注意,每次修改配置之后,要求重新部署整个项目,而tomcate这样的服务器,还必须重新启动服务器
  2. Struts的Action必需是thread-safe方式,它仅仅允许一个实例去处理所有的请求。所以action用到的所有的资源都必需统一同步,这个就引起了线程安全的问题。
  3. 测试不方便. Struts的每个Action都同Web层耦合在一起,这样它的测试依赖于Web容器,单元测试也很难实现。不过有一个Junit的扩展工具Struts TestCase可以实现它的单元测试。
  4. 类型的转换. Struts的FormBean把所有的数据都作为String类型,它可以使用工具Commons-Beanutils进行类型转化。但它的转化都是在Class级别,而且转化的类型是不可配置的。类型转化时的错误信息返回给用户也是非常困难的。
  5. 对Servlet的依赖性过强. Struts处理Action时必需要依赖ServletRequest和ServletResponse,所有它摆脱不了Servlet容器。
  6. 前端表达式语言方面.Struts集成了JSTL,所以它主要使用JSTL的表达式语言来获取数据。可是JSTL的表达式语言在Collection和索引属性方面处理显得很弱。
  7. 对Action执行的控制困难. Struts创建一个Action,如果想控制它的执行顺序将会非常困难。甚至你要重新去写Servlet来实现你的这个功能需求。
  8. 对Action执行前和后的处理. Struts处理Action的时候是基于class的hierarchies,很难在action处理前和后进行操作。
  9. 对事件支持不够.在struts中,实际是一个表单Form对应一个Action类(或DispatchAction),换一句话说:在Struts中实际是一个表单只能对应一个事件,struts这种事件方式称为application event,application event和component event相比是一种粗粒度的事件.
5.4struts2 框架的核心控制器是什么?它有什么作用?

1)Struts2 框架的核心控制器是 StrutsPrepareAndExecuteFilter。
2)作用:
负责拦截由/*指定的所有用户请求,当用户请求到
达时,该 Filter 会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action 结尾,这时请求将被转入 struts2 框架处理,否则struts2 框架将略过该请求的处理。可以通过常量"struts.action.extension"修改 action 的后缀,如:
< constant name=“struts.action.extension” value=“do”/ >
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。
< constant name=“struts.action.extension” value=“do,go”/ >

5.5 struts2 默认能解决 get 和 post 提交方式的乱码问题吗?

不能。struts.i18n.encoding=UTF-8 属性值只能解析 POST 提交下的乱码问题。

5.6 值栈 ValueStack 的原理与生命周期?

1)ValueStack 贯穿整个 Action 的生命周期,保存在 request 域中,所以ValueStack 和 request 的生命周期一样。当 Struts2 接受一个请求时,会迅速创建 ActionContext,ValueStack,action。然后把 action 存放进 ValueStack,所以 action 的实例变量可以被 OGNL 访问。 请求来的时候,action、ValueStack 的生命开始,请求结束,action、 ValueStack 的生命结束;
2)action 是多例的,和 Servlet 不一样,Servelt 是单例的;
3)每个 action 的都有一个对应的值栈,值栈存放的数据类型是该 action 的实例,以及该 action 中的实例变量,Action 对象默认保存在栈顶;
4)ValueStack 本质上就是一个 ArrayList;
5)关于 ContextMap,Struts 会把下面这些映射压入 ContextMap 中:
parameters : 该 Map 中包含当前请求的请求参数
request : 该 Map 中包含当前 request 对象中的所有属性 session :该 Map 中包含当前 session 对象中的所有属性
application :该 Map 中包含当前 application 对象中的所有属性
attr:该 Map 按如下顺序来检索某个属性: request, session, application
6)使用 OGNL 访问值栈的内容时,不需要#号,而访问 request、session、application、attr 时,需要加#号;
7)注意: Struts2 中,OGNL 表达式需要配合 Struts 标签才可以使用。如:< s:property value=“name”/ >
8)在 struts2 配置文件中引用 ognl 表达式 ,引用值栈的值 ,此时使用的"$",而不是#或者%;

5.7ActionContext、ServletContext、pageContext 的区别?

1)ActionContext 是当前的 Action 的上下文环境,通过 ActionContext 可以获取到 request、session、ServletContext 等与 Action 有关的对象的引用;
2)ServletContext 是域对象,一个 web 应用中只有一个 ServletContext,生命周期伴随整个 web 应用;
3)pageContext 是 JSP 中的最重要的一个内置对象,可以通过 pageContext 获取其他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结束时,pageContext 销毁,生命周期是 JSP 四个域对象中最小的。

5.8result 的 type 属性中有哪几种结果类型?

一共 10 种:
dispatcher
struts 默认的结果类型,把控制权转发给应用程序里的某个资源不能把控制权转发给一个外
部资源,若需要把控制权重定向到一个外部资源, 应该使用
redirect 结果类型
redirect 把响应重定向到另一个资源(包括一个外部资源)
redirectAction 把响应重定向到另一个 Action
freemarker、velocity、chain、httpheader、xslt、plainText、stream

5.9servlet 和 filter 的区别

Filter 可认为是 Servlet 的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。它与 Servlet的区别在于:它不能直接向用户生成响应。完整的流程是:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

2 Hibernate

工作原理:
1.读取并解析配置文件
2.读取并解析映射信息,创建SessionFactory
3.打开Session
4.创建事务Transation
5.持久化操作
6.提交事务
7.关闭Session
8.关闭SesstionFactory

为什么要使用Hibernate(即它的优点):
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

1.Hibernate 的 jar 包

最基本的 Hibernate3.3.2 之 JAR 包(必要):
hibernate3.jar 核心 JAR 包
antlr.jar Another Tool for Language Recognition,可以构造语言识别器,解析HQL 需要
commons-collections.jar 包含了一些 Apache 开发的集合类,功能比 Java.util.*强大
dom4j.jar 越来越多的 Java 软件都在使用 dom4j 来操作 XML,Hibernate 也不例外
javassist.jar 操作字节码,跟 cglib 相关
jta.jar 定义 JTA 规范的 JAR 包,当 Hibernate 使用 JTA 的时候需要
slf4j.jar 整合各志框架种日的工具
slf4j-nop.jar 包含了对 slf4j.jar 的实现类

2.Hibernate 的核心配置文件

Hibernate 框架支持 properties 和 xml 两种方式的 Hibernate 属性的配置,对应的两种核心配置文件为:
hibernate.properties 配置常用的属性,必须手动加载 hbm 文件或持久化类。(了解)
hibernate.cfg.xml 配置常用的属性,配置加载 hbm 映射,配置缓存策略等。(推荐)

3.Hibernate 的核心 API 接口

所有的 Hibernate 应用中都会访问 Hibernate 的 5 个核心接口。
Configuration 接口:配置 Hibernate,根启动 Hibernate,创建 SessionFactory 对象。
SessionFactory 接口:初始化 Hibernate,充当数据存储源的代理,创建 Session 对象。
Session 接口:负责保存、更新、删除、加载和查询对象。
Transaction 接口:管理事务。
Query 和 Criteria 接口:执行数据库查询。

Configuration 接口
Configuration 对象用于配置并且启动 Hibernate。Hibernate 应用通过 Configuration 实例来指定对象-关系映射文件的位置或者动态配置 Hibernate 的属性,然后创建 SessionFactory 实例。
SessionFactory 接口
一个 SessionFactory 实例对应一个数据存储源,应用从 SessionFactory 中获得 Session 实例。
SessionFactory 有以下特点:
它是线程安全的,这意味着它的同一个实例可以被应用的多个线程共享。
它是重量级的,这意味着不能随意创建或销毁它的实例。如果应用只访问一个数据库,只需要创建一个 SessionFactory 实例,在应用初始化的时候创建该实例。如果应用同时访问多个数据库,则需要为每个数据库创建一个单独的 SessionFactory 实例。
之所以称 SessionFactory 是重量级的,是因为它需要一个很大的缓存,用来存放预定义的SQL 语句以能映射元数据等。用户还可以为 SesionFactory 配置一个缓存插件,这个缓存插件被称为 Hibernate 的第二级缓存。,该缓存用来存放被工作单元读过的数据,将来其他工作单元可能会重用这些数据,因此这个缓存中的数据能够被所有工作单元共享。一个工作单元通常对应一个数据库事务。
Session 接口
Session 接口是 Hibernate 应用使用最广泛的接口。Session 也被称为持久化管理器,它提供了和持久化相关的操作,如添加、更新、删除、加载和查询对象。
Session 有以下特点:
不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个 Session 实例。Session 实例是轻量级的,所谓轻量级,是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建和销毁 Session 对象,例如为每个客户请示分配单独的 Session实例,或者为每个工作单元分配单独的 Session 实例。Session 有一个缓存,被称为 Hibernate 的第一级缓存,它存放被当前工作单元加载的对象。每个 Session 实例都有自己的缓存,这个 Sesion 实例的缓存只能被当前工作单元访问。
Transaction 接口
Transaction 接口是 Hibernate 的数据库事务接口,它对底层的事务接口做了封装,底层事务
接口包括:
JDBC API、JTA(Java Transaction API)、CORBA(Common Object Requet Broker Architecture)
API
Hibernate 应用可通过一致的 Transaction 接口来声明事务边界,这有助于应用在不同的环境容器中移植。尽管应用也可以绕过 Transaction 接口,直接访问底层的事务接口,这种方法不值得推荐,因为它不利于应用在不同的环境移植。
Query 和 Criteria 接口
Query 和 Criteria 接口是 Hibernate 的查询接口,用于向数据库查询对象,以及控制执行查询的过程。Query 实例包装了一个 HQL 查询语句,HQL 查询语句和 SQL 查询语句有些相似,但 HQL 查询语句是面向对象的,它引用类句及类的属性句,而不是表句及表的字段句。Criteria 接口完全封装了基于字符串的查询语句,比 Query 接口更加面向对象,Criteria 接口擅长执行动态查询。
Session 接口的 find()方法也具有数据查询功能,但它只是执行一些简单的 HQL 查询语句的快捷方法,它的功能远没有 Query 接口强大。

3.hibernate 常用注解

@Entity:声明实体 bean,每一个持久化 POJO 类都是一个实体 bean,这可以通过在类的定
义中使用@Entity 注解来进行声明:
@Id:注解则声明了该实体 bean 的标识属性,对应相应表使用 id 列作为主键列
@Table:是类一级的注解, 通过@Table 注解可以为实体 bean 映射指定表(table),目录
(catalog)和 schema 的名字. 如果没有定义@Table,那么系统自动使用默认值:实体的短类名
(不附带包名).
@Transient:实体 bean 中所有的非 static 非 transient 的属性都可以被持久化, 除非你将其
注解为@Transient,所有没有定义注解的属性等价于在其上面添加了@Basic 注解.
@GeneratedValue:定义该标识符的生成策略
AUTO - 可以是 identity column 类型,或者 sequence 类型或者 table 类型,取决于不同的底层
数据库.
TABLE - 使用表保存 id 值
IDENTITY - identity column
SEQUENCE - sequence
@OneToOne 注解可以建立实体 bean 之间的一对一的关联.
@ManyToOne 注解来定义多对一关联

4.Hibernate 的执行流程?你的理解?

1.通过 Configuration.configure()读取并解析 hibernate.cfg.xml 配置文件;
2.由 hibernate.cfg.xml 中的< mapping resource=”com/xx/User.hbm.xml”/>读取并解析映射信息;
3.通过 config.buildSerssionFactory()创建 SessionFactory;
4.sessionFactory.openSession()打开 session;
5.session.beginTransaction()创建事务 transation;
6.persistent operate(持久化操作);
7.session.getTransaction().commit()提交事务;
8.关闭 session;
9.关闭 SessionFactory。

理解:

  1. 面向对象设计的软件内部运行过程可以理解成就是在不断创建各种新对象、建立对象之间的关系,调用对象的方法来改变各个对象的状态和对象消亡的过程,不管程序运行的过程和操作怎么样,本质上都是要得到一个结果,程序上一个时刻和下一个时刻的运行结果的差异就表现在内存中的对象状态发生了变化。
  2. 为了在关机和内存空间不够的状况下,保持程序的运行状态,需要将内存中的对象状态保存到持久化设备和从持久化设备中恢复出对象的状态,通常都是保存到关系数据库来保存大量对象信息。从Java程序的运行功能上来讲,保存对象状态的功能相比系统运行的其他功能来说,应该是一个很不起眼的附属功能,java采用jdbc来实现这个功能,这个不起眼的功能却要编写大量的代码,而做的事情仅仅是保存对象和恢复对象,并且那些大量的jdbc代码并没有什么技术含量,基本上是采用一套例行公事的标准代码模板来编写,是一种苦活和重复性的工作。
  3. 通过数据库保存java程序运行时产生的对象和恢复对象,其实就是实现了java对象与关系数据库记录的映射关系,称为ORM(即Object RelationMapping),人们可以通过封装JDBC代码来实现了这种功能,封装出来的产品称之为ORM框架,Hibernate就是其中的一种流行ORM框架。使用Hibernate框架,不用写JDBC代码,仅仅是调用一个save方法,就可以将对象保存到关系数据库中,仅仅是调用一个get方法,就可以从数据库中加载出一个对象。
  4. 使用Hibernate的基本流程是:配置Configuration对象、产生SessionFactory、创建session对象,启动事务,完成CRUD操作,提交事务,关闭session。
  5. 使用Hibernate时,先要配置hibernate.cfg.xml文件,其中配置数据库连接信息和方言等,还要为每个实体配置相应的hbm.xml文件,hibernate.cfg.xml文件中需要登记每个hbm.xml文件。
  6. 在应用Hibernate时,重点要了解Session的缓存原理,级联,延迟加载和hql查询。
5.Hibernate 问题合集
5.1Hibernate 中 get 和 load 有什么不同之处?

把 get 和 load 放到一起进行对比是 Hibernate 面试时最常问到的问题,这是因为只有正确理解 get()和 load()这二者后才有可能高效地使用 Hibernate。get 和 load 的最大区别是,如果在缓存中没有找到相应的对象,get 将会直接访问数据库并返回一个完全初始化好的对象,而这个过程有可能会涉及到多个数据库调用;而 load 方法在缓存中没有发现对象的情况下,只会返回一个代理对象,只有在对象 getId()之外的其它方法被调用时才会真正去访问数据库,这样就能在某些情况下大幅度提高性能。

5.2Hibernate 中 save、persist 和 saveOrUpdate 这三个方法的不同之处?

除了 get 和 load,这又是另外一个经常出现的 Hibernate 面试问题。 所有这三个方法,也就是 save()、saveOrUpdate()和 persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别。例如,save()只能 INSERT 记录,但是 saveOrUpdate()可以进行 记录的 INSERT和 UPDATE。还有,save()的返回值是一个 Serializable 对象,而 persist()方法返回值为 void。

5.3Hibernate 中的命名 SQL 查询指的是什么?

Hibernate 的这个面试问题同 Hibernate 提供的查询功能相关。命名查询指的是用<sqlquery>标签在影射文档中定义的 SQL 查询,可以通过使用 Session.getNamedQuery()方法对它进行调用。命名查询使你可以使用你所指定的一个名字拿到某个特定的查询。 Hibernate中的命名查询可以使用注解来定义,也可以使用我前面提到的 xml 映射问句来定义。在Hibernate 中,@NameQuery 用来定义单个的命名查询,@NameQueries 用来定义多个命名查询。

5.4Hibernate 中的 SessionFactory 有什么作用? SessionFactory 是线程安全的吗?

这也是 Hibernate 框架的常见面试问题。顾名思义,SessionFactory 就是一个用于创建Hibernate 的 Session 对象的工厂。SessionFactory 通常是在应用启动时创建好的,应用程序中的代码用它来获得 Session 对象。作为一个单个的数据存储,它也是 线程安全的,所以多个线程可同时使用同一个 SessionFactory。Java JEE 应用一般只有一个 SessionFactory,服务于客户请求的各线程都通过这个工厂来获得 Hibernate 的 Session 实例,这也是为什么SessionFactory 接口的实现必须是线程安全的原因。还有,SessionFactory 的内部状态包含着同对象关系影射有关的所有元数据,它是不可变的,一旦创建好后就不能对其进行修改了。

5.5Hibernate 中的 Session 指的是什么? 可否将单个的 Session 在多个线程间进行共享?

前面的问题问完之后,通常就会接着再问这两个问题。问完 SessionFactory 的问题后就该轮到 Session 了。Session 代表着 Hibernate 所做的一小部分工作,它负责维护者同数据库的链接而且 不是线程安全的,也就是说,Hibernage 中的 Session 不能在多个线程间进行共享。虽然 Session 会以主动滞后的方式获得数据库连接,但是 Session 最好还是在用完之后立即将其关闭。

5.6 说一下Hibernate 中的缓存机制?二级缓存指的是什么?

为了降低应用程序访问物理数据源(数据库)的频率,从而提高应用程序的性能;缓存内的数据是物理数据源中数据的复制,应用程序运行时从缓存中读取数据,同步缓存和物理数据源中的数据;一级缓存:Session缓存,session的生命周期对应一个事务,所以是事务范围内的缓存,在一级缓存中,持久化类的每个实例都具有唯一的OID;二级缓存:SessionFactory缓存,他的生命周期对应应用程序的生命周期,所以二级缓存是进程或者集群范围内的缓存(并发问题),需要采用适当的并发访问策略,为被缓存的数据提供事务隔离级别。
注意:hibernate更新、删除、新增数据时都会同步到缓存。

这是同 Hibernate 的缓存机制相关的第一个面试问题,不出意外后面还会有更多这方面的问题。二级缓存是在 SessionFactory 这个级别维护的缓存,它能够通过节省几番数据库调用往返来提高性能。还有一点值得注意,二级缓存是针对整个应用而不是某个特定的 session 的。

5.7Hibernate 中的查询缓存指的是什么?

这个问题有时是作为上个 Hibernate 面试问题的后继问题提出的。查询缓存实际上保存的是sql 查询的结果,这样再进行相同的 sql 查询就可以之间从缓存中拿到结果了。为了改善性能,查询缓存可以二级缓存一起来使用。Hibernate 支持用多种不同的开源缓存方案,比如 EhCache,来实现查询缓存。
按照以下思路来回答:
(1)首先说清楚什么是缓存
(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存
(3)最后再说如何配置Hibernate的二级缓存。
1,缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似HashMap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。
2,Hibernate的Session就是一种缓存,我们通常将之称为Hibernate的一级缓存,当想使用session从数据库中查询出一个对象时,Session也是先从自己内部查看是否存在这个对象,存在则直接返回,不存在才去访问数据库,并将查询的结果保存在自己内部。
由于Session代表一次会话过程,一个Session与一个数据库连接相关连,所以Session最好不要长时间保持打开,通常仅用于一个事务当中,在事务结束时就应关闭。并且Session是线程不安全的,被多个线程共享时容易出现问题。通常只有那种全局意义上的缓存才是真正的缓存应用,才有较大的缓存价值,因此,Hibernate的Session这一级缓存的缓存作用并不明显,应用价值不大。Hibernate的二级缓存就是要为Hibernate配置一种全局缓存,让多个线程和多个事务都可以共享这个缓存。我们希望的是一个人使用过,其他人也可以使用,session没有这种效果。
3,二级缓存是独立于Hibernate的软件部件,属于第三方的产品,多个厂商和组织都提供有缓存产品,例如,EHCache和OSCache等等。在Hibernate中使用二级缓存,首先就要在hibernate.cfg.xml配置文件中配置使用哪个厂家的缓存产品,接着需要配置该缓存产品自己的配置文件,最后要配置Hibernate中的哪些实体对象要纳入到二级缓存的管理中。明白了二级缓存原理和有了这个思路后,很容易配置起Hibernate的二级缓存。
扩展知识:一个SessionFactory可以关联一个二级缓存,也即一个二级缓存只能负责缓存一个数据库中的数据,当使用Hibernate的二级缓存后,注意不要有其他的应用或SessionFactory来更改当前数据库中的数据,这样缓存的数据就会与数据库中的实际数据不一致。

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

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

它们的区别在于维护的关系不同:
一对多关联映射是指在加载一的一端数据的同时加载多的一端的数据多对一关联映射是指在加载多的一端数据的同时加载一的一端的数据。

5.9Hibernate是如何延迟加载?
  1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
  2. Hibernate3 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
    延迟加载要在session范围内,用到的时候再加载;opensessioninview是在web层写了一个filter来打开和关闭session,这样就表示在一次request过程中session一直开着,保证了延迟加载在session中的这个前提。
5.10如何优化Hibernate?

1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
6. 继承类使用显式多态
7. 表字段要少,表关联不要怕多,有二级缓存撑腰

6 openSession 和currentSession的区别

1.currentSession会和当前的事务绑定,openSession则不会;

2.currentSession在事务回滚或事物提交之后会自动关闭session,openSession则 需要手动的关闭。

使用getCurrentSession需要配置:
如果是使用本地事务(jdbc事务)
< property name=”hibernate.current_session_context_class”>thread< /property>

如果是使用全局事务(jta事务)
< property name=”hibernate.current_session_context_class”>jta< /property>

getCurrentSession:当前Session对象
openSession:打开一个新的Session对象

原文链接:https://blog.csdn.net/faithpassion/article/details/38732071

3 Spring

1.谈谈你对 Spring 的理解

Spring 是一个开源框架,为简化企业级应用开发而生。Spring 可以是使简单的 JavaBean 实现以前只有 EJB 才能实现的功能。Spring 是一个 IOC 和 AOP 容器框架。
Spring 容器的三大 主要核心是:
控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反转的思想。
依赖注入(DI),spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等。公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。

2.Spring 中的设计模式

a. 单例模式——spring 中两种代理方式,若目标对象实现了若干接口,spring 使用 jdk 的java.lang.reflect.Proxy类代理。若目标兑现没有实现任何接口,spring 使用 CGLIB 库生成目标类的子类。
单例模式——在 spring 的配置文件中设置 bean 默认为单例模式。
b. 模板方式模式——用来解决代码重复的问题。
比如:RestTemplate、JmsTemplate、JpaTemplate
d. 前端控制器模式——spring 提供了前端控制器 DispatherServlet 来对请求进行分发。
e. 试图帮助(view helper)——spring 提供了一系列的 JSP 标签,高效宏来帮助将分散的代码整合在试图中。
f. 依赖注入——贯穿于 BeanFactory/ApplacationContext 接口的核心理念。
g. 工厂模式——在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用同一个接口来指向新创建的对象。Spring 中使用 beanFactory 来创建对象的实例。

3. Spring 的常用注解

Spring 在 2.5 版本以后开始支持注解的方式来配置依赖注入。可以用注解的方式来代替 xml 中 bean 的描述。注解注入将会被容器在 XML 注入之前被处理,所以后者会覆盖掉前者对于同一个属性的处理结果。
注解装配在 spring 中默认是关闭的。所以需要在 spring 的核心配置文件中配置一下才能使用基于注解的装配模式。配置方式如下:
< context:annotation-config />
常用的注解:
@Required:该注解应用于设值方法
@Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
@Qualifier:该注解和@Autowired 搭配使用,用于消除特定 bean 自动装配的歧义。

4.简单介绍一下 Spring bean 的生命周期

bean 定义:在配置文件里面用来进行定义。
bean 初始化:有两种方式初始化:
1.在配置文件中通过指定 init-method 属性来完成
2.实现 org.springframwork.beans.factory.InitializingBean 接口
bean 调用:有三种方式可以得到 bean 实例,并进行调用
bean 销毁:销毁有两种方式
1.使用配置文件指定的 destroy-method 属性
2.实现 org.springframwork.bean.factory.DisposeableBean 接口

5.为什么要使用 spring?或spring有什么优点好处?

Spring是一个轻量级的控制反转、面向切面的容器框架;解决企业开发的复杂性;
IOC容器:创建程序中的对象并管理其生命周期,控制反转,解耦,非侵入式编程(bean对象不依赖于spring框架的类);IOC容器在对象初始化时不等对象请求就主动将依赖传递给对象;
AOP(事务管理,日志等):分离应用的业务逻辑和系统级别的服务,使我们更加关注业务;
组件化:将简单的组件经过合理的配置,可以组合成复杂的应用程序;
对主流应用框架提供了良好的支持,并提供了很多模板类(JDBC Template、Redis Template等)。

6.解释一下什么是 aop?

面向切面编程,通过预编译方式(AspectJ)和运行期动态代理(JDK(默认)、CGLib动态代理)实现在不修改代码的情况下动态添加程序功能的的技术。
主要的功能:日志记录,性能统计,安全控制,事务处理,异常处理等。
通知:前置、后置、环绕、异常,返回后通知;
切面
切点
在什么时候切入到什么位置;

7.spring有哪些主要模块?

三个核心组件:core,bean,context,其它的如AOP,tx,common等 IOC,DI

8.spring常用的注入方式有哪些?

构造器注入,官方推荐使用;(效率高,无属性对象)
属性,setter注入;
基于注解的注入。

9.spring 支持几种bean的作用域?

singleton:单例(默认),一个bean容器(每个context都对应一个容器)中只存在一份;
prototype:每次请求(使用)都会创建新的实例,destroy方式不生效;
注:singleton注册的bean在服务器启动时初始化;而prototype只有在被调用的时候才初始化;
request:每次http请求都会创建一个实例,且仅在当前的request范围内有效;
session:会话,在session的范围内有效,不同session使用不同的实例;
global-session:所有会话都共享一个实例;

10.spring的事务隔离

https://blog.csdn.net/weixin_45044097/article/details/103037246

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值