Java面试题:框架
Hibernate
1.Hibernate 工作原理及为什么要用?
原理:
- 读取并解析配置文件
- 读取并解析映射信息
- 创建 SessionFactory
- 打开 Sesssion
- 创建事务 Transation
- 持久化操作
- 提交事务
- 关闭 Session
- 关闭 SesstionFactory
为什么要用
- 对 JDBC 访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate 是一个基于 JDBC 的主流持久化框架,是一个优秀的 ORM 实现,他很大程度的简化 DAO 层的编码工作。
- hibernate 使用 Java 反射机制,而不是字节码增强程序来实现透明性。
- hibernate 的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
2.hibernate的get()和load()方法的去别?
-
返回值:
get()返回的是查询出来的实体对象,而 load()查询出来的是一个目标实体的代理对象。
-
查询时机:
get()在调用的时候就立即发出 SQL 语句查询,而 load()在访问非 ID 属性的时候才会发出查询语句并且将被代理对象 target 填充上,但是如果这个动作发生在 Session 被关闭后的话就会抛出 LazyInitializationException。
-
查询结果为空时:
get()抛出 NullPointerException load()抛出 ObjectNotFoundException
3.hibernate 的懒加载有几种禁用方法?
在 Hibernate 框架中,当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,这时Hibernate 用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。
我们所说的懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。
- 使用代理对象: Hibernate.initialize(“代理对象”);
- 在需要禁用懒加载的映射文件中显示的加入 lazy = “false”
- 使用 openSessionInView【需要借助于过滤器】 需要在 web.xml 文件中配置
4.Hibernate和JDBC对比
- 相同点:
- 两者都是java数据库操作的中间件
- 两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭
- 两者都可以对数据库的更新操作进行显示的事务处理
- 不同点:
- JDBC是SUN公司提供的一套操作数据库的规范,使用java代码操作数据库.Hibernate是一个基于jdbc的主流持久化框架,对JDBC访问数据库的代码做了封装.
- 使用的SQL语言不同JDBC使用的是基于关系型数据库的标准的SQL语言,Hibernate使用的是HQL(Hibernate Query Language)语言.
- 操作对象不同:JDBC操作的是数据,将数据通过sql语句直接传送到数据库中执行,hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中
- 数据状态不同:JDBC操作的数据是
瞬时
的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的.
5.ORM思想
ORM指的是对象关系型映射(Object RelationShip Mapping),指的是我们通过创建实体类对象和数据库中的表关系进行一一对应,来实现通过操作实体类对象来更改数据库里边的数据信息,这里边起到的关键作用的是通过Hibernate的映射文件+Hibernate的核心配置文件
6.谈谈Hibernate里面持久态对象的三种状态
- 瞬时态(临时态,自由态):不存在持久化标识OID,尚未Hibernate Session关联对象,被认为处于瞬时态,失去引用将被JVM回收
- 持久态:存在持久化标识OID,但没有与当前Hibernate Session关联,并且相关联的session没有关闭,并且事务未提交.
- 托管态(离线态,游离态):存在持久化标识,但没有与当前session关联,脱管状态改变Hibernate不能检测到
区分三种状态
判断对象是否有OID,判断对象是否与session关联(被一级缓存引用)
7.Hibernate中有哪几种查询数据的方式
查询方式导航对象图查询
,OID查询
,HQL查询
,QBC查询
,本地SQL查询
.
-
HQL:
-
HQL:Hibernate提供的一种查询语言,一般通过创建query对象进行hql语句的操作,HQL语言和普通的sql很相似,区别在于,普通的SQL操作数据库表和字段,HQL操作实体类和属性
-
常用的HQL语句
查询所有:from 实体类名称
条件查询:from 实体类名称 where 属性名称=?
排序查询:from 实体类名称 order by 实体类属性名称 asc/desc
分页查询:关键的两个设置,一个是**setFirstResult()<设置起始页从第几条开始>**,另一个是**setMaxResult()<设置页容量>**设置页容量>设置起始页从第几条开始>
-
使用HQL查询操作时候,使用Query对象
- 创建Query对象,写HQL语句
- 调用Query对象里面的方法得到结果
-
-
QBC
使用HQL查询需要HQL语句实现,但是使用QBC时候,不需要写语句,使用方法实现
常用方法有:
查询所有:创建criteria对象,调用他的
list()
方法即可条件查询:创建一个criteria对象,调用它的
add
方法来实现条件的设置,在这个方法里面我们使用Restrictions
这个类里面的静态方法来实现,如:restrictions.rq(),Restrictions.like().
分页查询:创建一个criteria对象,分页方法和HQL的分页方法一样,关键的两个设置,一个是**setFirstResult()<设置起始页从第几条开始>**,另一个是**setMaxResult()<设置页容量>**设置页容量>设置起始页从第几条开始>
模糊查询:调用
restrictons.like()
方法排序查询:创建一个criteria对象,调用
addOrder()
方法来实现排序,在这个方法里面通过Order.desc()
方法来实现排序统计查询:创建一个criteria对象
criteria.setProjection(Projection.rowCount());criteria.uniqueResult();
8.Hibernate中的SessionFactory有什么作用?SessionFactory是线程安全的吗?
SessionFactory 就是一个用于创建Hibernate的Session对象的工厂。SessionFactory通常是在应用启动时创建好的,应用程序中的代码用它来获得Session对象。作为一个单个的数据存储,它也是线程安全的,所以多个线程可同时使用同一个SessionFactory。JavaEE应用一般只有一个SessionFactory,服务于客户请求的各线程都通过这个工厂来获得Hibernate的Session实例、这也是为什么SessionFactory接口的实现必须是线程安全的原因。还有,SessionFactory的内部状态包含着同对象关系影射有关的所有元数据,它是不可变的,一旦创建好后就不能对其进行修改了。
9.Hibernate中的Session指的是什么?可否将单个的Session在多个线程间进行共享?
Session代表着Hibernate所做的一小部分工作,它负责维护者同数据库的链接而且不是线程安全的,也就是说,Hibernage中的Session 不能在多个线程间进行共享。虽然Session会以主动滞后的方式获得数据库连接,但是Session最好还是在用完之后立即将其关闭。
Spring
1.说说spring的工作流程
- 创建配置文件applicationContext.xml
- 编写配置文件(加入一些对象的配置信息)
- Spring内部采用工厂模式,配合xml解析+反射技术,可以根据用户的配置,生成相应的对象
- 工厂提供一个getBean方法,从工厂中获取对象
- 操作对象的方法,属性
2.spring对象创建的三种方式
- 无参构造
- 实例工厂
- 静态工厂
3.不使用注解的情况下,如果给对象注入值的话,有几种方式
- set注值
- 构造器注值
- 名称空间注值
- Spel注值
- 注入java复杂类型
- 注入对象类型
常用set注值
和对象类型注值
set 我们通过配置文件给对象赋值,就相当于我们使用对象里面属性的set方法给对象赋值
(图一)
(图二)
对象类型注值 使用ref表示注入一个已经存在的对象(默认还是调用set方法注入)
4.常用的spring注解开发步骤
-
创建对象
导入jar包(IoC基本)spring-aop-4.2.4.jar
导入约束context
开启注解扫描
<context componect-scan base-package="包名">
在要创建的对象上使用
@Component
、@Repository
、@Service
、@Controller
如果要产生的对象对多例加上
@Scope(value="prototype")
-
注入对象
在要注入对象的前面加 @Autowired 按类型注入
@Reosource(name=”XXX”) 按bean的id注入
5.谈谈spring的事务管理
spring提供的事务管理可以分为两类:编程式和声明式。
编程式:主要使用transactionTemplate,省略了部分的提交、回滚、一系列的事务对象定义,需注入事务管理对象,比较灵活,但是代码量大,存在重复的代码比较多。
编程式事务需要你在代码中直接加入处理事务的逻辑,可能需要在代码中显式调beginTransaction()、 commit()、 rollback()等事务管理相关的方法,如在执行 a 方法时候需要事务处理,你需要在 a 方法开始时候开启事务,处理完后。在方法结束时候,关闭事务。
声明式:使用TransactionProxyFactoryBean:PROPAGATION_REQUIRED、readOnly,围绕Proxy的动态代理能够自动的提交和回滚事务,在 a 方法外围添加注解或者直接在配置文件中定义,a 方法需要事务处理,在spring 中会通过配置文件在 a 方法前后拦截,并添加事务。
二者区别:编程式事务侵入性比较强,但处理粒度更细。
6.spring原理
-
IoC(Inversion of Control):控制反转,依赖注入
- 概念:控制权由对象本身转向容器,有容器根据配置文件去创建实例并创建各个实例之间的依赖关系;
- 依赖IoC容器负责管理bean,有两种,一种是
BeanFactory
,另一种是ApplicationContext
,但是ApplicationContext
继承于BeanFactory
- 核心:Bean工厂,在Spring中,Bean工厂创建的各个实例称作bean
-
AOP(Aspect-Oriented Programming):面向切面编程
-
代理的两种方式:
静态代理:
针对每个具体类分别编写代理类;
针对一个接口编写一个代理类;
动态代理:
针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类
-
AOP的主要原理:
动态代理的实现:
JDK中的Proxy
和Cglib
,Spring规定对于有接口的类用JDK Proxy
,对于无接口和抽象类用Cglib,虽然Cglib均可以代理,但是Cglib复杂,效率低。但是Cglib有例外,就是代理的类中不能是final修饰的类或者类中有final方法。
-
7.使用Spring有什么好处?
- Spring能有效地组织你的中间层对象,无论你是否选择使用了B。如果你仅仅使用了Struts 或其他的包含了12EE特有APIs的framework.你会发现Spring关注了遗留下的问题。
- Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题、它减少了系统的可测试性和面向对象特性。
- Spring能消除使用各种各样格式的属性定制文件的需要、在整个应用和工程中,可通过一种一致的方法来进行配置。曾经感到迷惑,一个特定类要查找迷幻般的属性关键字或系统。为此不得不读Javadoc乃至源编码吗?有了Sping.你可很简单地看到类的avaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。
- Spring 能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
- Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
- 使用Spring构建的应单元测试。
- Spring 能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOS或local EJBs来实现业务接口,却不会影响调用代码。
- Sping帮助你解决许多问题而无需使用EJB。Spring 能提供一种EJB的替换物、它们适于许多web应用。例如Spring 能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
- Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R mapping产品(如Hibernate)。
Sping确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。 总结起来,Spring有如下优点:
- 低侵入式设计,代码污染极低
- 独立于各种应用服务器,可以真正实现Write Once,Run Anywhere的承诺
- Spring的DI机制降低了业务对象替换的复杂性
- Spring并不完全依赖Spring,开发者可自由选用spring框架的部分或者全部结构
8.spring 设置为单例,线程安全问题怎么解决?
spring 的单例和我们设计模式中的单例还是有些区别的,设计模式中的单例是在整个应用中只存在一个单例,而 spring 中的单例是存在 IOC 容器中只有一个实例, spring 中的单例并不会影响到应用的并发访问,通常我们 spring中的线程安全问题是指的在业务逻辑中的那个问题, ThreadLocal 则从另一个角度来解决多线程的并发访问。
ThreadLocal 会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。 ThreadLocal 提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
Struts2
1.struts 可以是单例的吗? 为什么?
在 Struts2 中 action 必须为多例,主要原因在于请求数据和返回数据大部分封装到了 action 中,用于实例化变量,这样以来,如果将 action 设置成单例模式,则多个线程访问的时候,就会共享这些数据,从而引起数据混乱或者线程安全问题!
SpringMVC
1.hibernate 的懒加载有几种禁用方法?
在 Hibernate 框架中,当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,这时Hibernate 用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。
我们所说的懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。
- 使用代理对象: Hibernate.initialize(“代理对象”);
- 在需要禁用懒加载的映射文件中显示的加入 lazy = “false”
- 使用 openSessionInView【需要借助于过滤器】 需要在 web.xml 文件中配置
MyBatis
持续更新中…
转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!