Java面试题:框架

Java面试题:框架


Hibernate


1.Hibernate 工作原理及为什么要用?

原理:

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

为什么要用

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

2.hibernate的get()和load()方法的去别?

  • 返回值:

    get()返回的是查询出来的实体对象,而 load()查询出来的是一个目标实体的代理对象。

  • 查询时机:

    get()在调用的时候就立即发出 SQL 语句查询,而 load()在访问非 ID 属性的时候才会发出查询语句并且将被代理对象 target 填充上,但是如果这个动作发生在 Session 被关闭后的话就会抛出 LazyInitializationException。

  • 查询结果为空时:

    get()抛出 NullPointerException load()抛出 ObjectNotFoundException


3.hibernate 的懒加载有几种禁用方法?

在 Hibernate 框架中,当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,这时Hibernate 用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。

我们所说的懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。

  1. 使用代理对象: Hibernate.initialize(“代理对象”);
  2. 在需要禁用懒加载的映射文件中显示的加入 lazy = “false”
  3. 使用 openSessionInView【需要借助于过滤器】 需要在 web.xml 文件中配置

4.Hibernate和JDBC对比

  1. 相同点:
    1. 两者都是java数据库操作的中间件
    2. 两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭
    3. 两者都可以对数据库的更新操作进行显示的事务处理
  2. 不同点:
    1. JDBC是SUN公司提供的一套操作数据库的规范,使用java代码操作数据库.Hibernate是一个基于jdbc的主流持久化框架,对JDBC访问数据库的代码做了封装.
    2. 使用的SQL语言不同JDBC使用的是基于关系型数据库的标准的SQL语言,Hibernate使用的是HQL(Hibernate Query Language)语言.
    3. 操作对象不同:JDBC操作的是数据,将数据通过sql语句直接传送到数据库中执行,hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中
    4. 数据状态不同:JDBC操作的数据是瞬时的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的.

5.ORM思想

ORM指的是对象关系型映射(Object RelationShip Mapping),指的是我们通过创建实体类对象和数据库中的表关系进行一一对应,来实现通过操作实体类对象来更改数据库里边的数据信息,这里边起到的关键作用的是通过Hibernate的映射文件+Hibernate的核心配置文件


6.谈谈Hibernate里面持久态对象的三种状态

  1. 瞬时态(临时态,自由态):不存在持久化标识OID,尚未Hibernate Session关联对象,被认为处于瞬时态,失去引用将被JVM回收
  2. 持久态:存在持久化标识OID,但没有与当前Hibernate Session关联,并且相关联的session没有关闭,并且事务未提交.
  3. 托管态(离线态,游离态):存在持久化标识,但没有与当前session关联,脱管状态改变Hibernate不能检测到

区分三种状态

判断对象是否有OID,判断对象是否与session关联(被一级缓存引用)


7.Hibernate中有哪几种查询数据的方式

查询方式导航对象图查询,OID查询,HQL查询,QBC查询,本地SQL查询.

  1. HQL:

    1. HQL:Hibernate提供的一种查询语言,一般通过创建query对象进行hql语句的操作,HQL语言和普通的sql很相似,区别在于,普通的SQL操作数据库表和字段,HQL操作实体类和属性

    2. 常用的HQL语句

      查询所有:from 实体类名称

      条件查询:from 实体类名称 where 属性名称=?

      排序查询:from 实体类名称 order by 实体类属性名称 asc/desc

      分页查询:关键的两个设置,一个是**setFirstResult()<设置起始页从第几条开始>**,另一个是**setMaxResult()<设置页容量>**

    3. 使用HQL查询操作时候,使用Query对象

      1. 创建Query对象,写HQL语句
      2. 调用Query对象里面的方法得到结果
  2. 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的工作流程

  1. 创建配置文件applicationContext.xml
  2. 编写配置文件(加入一些对象的配置信息)
  3. Spring内部采用工厂模式,配合xml解析+反射技术,可以根据用户的配置,生成相应的对象
  4. 工厂提供一个getBean方法,从工厂中获取对象
  5. 操作对象的方法,属性

2.spring对象创建的三种方式

  1. 无参构造
  2. 实例工厂
  3. 静态工厂

3.不使用注解的情况下,如果给对象注入值的话,有几种方式

  1. set注值
  2. 构造器注值
  3. 名称空间注值
  4. Spel注值
  5. 注入java复杂类型
  6. 注入对象类型

常用set注值对象类型注值

set 我们通过配置文件给对象赋值,就相当于我们使用对象里面属性的set方法给对象赋值

(图一)

(图二)

对象类型注值 使用ref表示注入一个已经存在的对象(默认还是调用set方法注入)


4.常用的spring注解开发步骤

  1. 创建对象

    导入jar包(IoC基本)spring-aop-4.2.4.jar

    导入约束context

    开启注解扫描<context componect-scan base-package="包名">

    在要创建的对象上使用@Component@Repository@Service@Controller

    如果要产生的对象对多例加上@Scope(value="prototype")

  2. 注入对象

    在要注入对象的前面加 @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原理

  1. IoC(Inversion of Control):控制反转,依赖注入

    1. 概念:控制权由对象本身转向容器,有容器根据配置文件去创建实例并创建各个实例之间的依赖关系;
    2. 依赖IoC容器负责管理bean,有两种,一种是BeanFactory,另一种是ApplicationContext,但是ApplicationContext继承于BeanFactory
    3. 核心:Bean工厂,在Spring中,Bean工厂创建的各个实例称作bean
  2. AOP(Aspect-Oriented Programming):面向切面编程

    1. 代理的两种方式:

      静态代理:

      针对每个具体类分别编写代理类;

      针对一个接口编写一个代理类;

      动态代理:

      针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类

    2. AOP的主要原理:

      动态代理的实现:JDK中的ProxyCglib,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 用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。

我们所说的懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。

  1. 使用代理对象: Hibernate.initialize(“代理对象”);
  2. 在需要禁用懒加载的映射文件中显示的加入 lazy = “false”
  3. 使用 openSessionInView【需要借助于过滤器】 需要在 web.xml 文件中配置


MyBatis



持续更新中…


转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦