面试问题2

使用Spring有什么好处
◆Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题,。
◆Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题,它减少了系统的可测试性和面向对象特性。
◆Spring能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中,可通过一种 一致的方法来进行配置。曾经感到迷惑,一个特定类要查找迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗?有了Spring,你可 很简单地看到类的JavaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。
◆Spring能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
◆Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
◆使用Spring构建的应用程序易于单元测试。
◆Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
◆Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
■Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R mapping产品(如Hibernate)。
Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。
总结起来,Spring有如下优点:
◆低侵入式设计,代码污染极低(切入式的,在外部编写,然后切入到代码中去)
◆独立于各种应用服务器(不依赖于web服务器),可以真正实现Write Once,Run Anywhere的承诺
◆Spring的DI机制降低了业务对象替换的复杂性(在配置文件中,bean配置的class是具体的实现类,但是类型是接口类型的,而且bean的实例化都是由Spring框架来实现而不需要用户自己来new,所以,当具体实现类更换时,其复杂度会大大降低。而且也减少了在更改的时候的遗漏)
◆Spring并不完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
:什么是Spring, 它有什么特点
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
◆轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并 且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
◆控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦 合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不 是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
◆面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的 业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们 并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是 一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生 成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
◆框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
jdbc、hibernate、ibatis的区别?
jdbc:手动 手动写sql,
delete、insert、update要将对象的值一个一个取出传到sql中,不能直接传入一个对象。
select:返回的是一个resultset,要从ResultSet中一行一行、一个字段一个字段的取出,然后封装到一个对象中,不直接返回一个对象。
ibatis的特点:半自动化
 sql要手动写
 delete、insert、update:直接传入一个对象
 select:直接返回一个对象  
hibernate:全自动
  不写sql,自动封装
  delete、insert、update:直接传入一个对象
  select:直接返回一个对象
Hibernate如何实现数据批量删除或更新?

 Query query=session.createQuery(”update”或”delete”);
 query.executeUpdate();
Hibernate中Criteria 和DetachedCriteria的作用是什么?
Criteria c=session.createCriteria(Customer.class);
 //设置条件
 c.add(Expression.ge(“字段名”,”值对象”))
  ge:>=
  gt:>
  le:<=
  lt:<
  eq:=
 //排序
 c.addOrder(Order.asc(“字段名”))
 //分页
c.setFirstResult(1)//从第2行开始提取
  c.setMaxResults(5)//返回5行
 DetachedCriteria产生时不需要session
 DetachedCriteria dc= DetachedCriteria.forClass(Customer.class)
 Criteria c=Dc.getExecutableCriteria(session)
hibernate的核心类是什么,它们的相互关系是什么?重要的方法是什么?
Configuration
SessionFactory
  Session如下方法
   Save
   load
   Update
   Delete
      Query q=CreateQuery(“from Customer where customerName=:customerName”)
   beginTransaction
   close
   Transaction
   Commit()
session.load()和session.get()的区别
Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。其区别在于:
如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException。
Load方法可返回实体的代理类实例,而get方法永远直接返回实体类。
load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。
Session在加载实体对象时,将经过的过程:
首先,Hibernate中维持了两级缓存。第一级缓存由Session实例维护,其中保持了Session当前所有关联实体的数据,也称为内部缓存。而第二级缓存则存在于SessionFactory层次,由当前所有由本 SessionFactory构造的Session实例共享。出于性能考虑,避免无谓的数据库访问,Session在调用数据库查询功能之前,会先在缓存中进行查询。首先在第一级缓存中,通过实体类型和id进行查找,如果第一级缓存查找命中,且数据状态合法,则直接返回。
之后,Session会在当前“NonExists”记录中进行查找,如果“NonExists”记录中存在同样的查询条件,则返回null。 “NonExists”记录了当前Session实例在之前所有查询操作中,未能查询到有效数据的查询条件(相当于一个查询黑名单列表)。如此一来,如果 Session中一个无效的查询条件重复出现,即可迅速作出判断,从而获得最佳的性能表现。
对于load方法而言,如果内部缓存中未发现有效数据,则查询第二级缓存,如果第二级缓存命中,则返回。
如在缓存中未发现有效数据,则发起数据库查询操作(Select SQL),如经过查询未发现对应记录,则将此次查询的信息在“NonExists”中加以记录,并返回null。
根据映射配置和Select SQL得到的ResultSet,创建对应的数据对象。
将其数据对象纳入当前Session实体管理容器(一级缓存)。
执行Interceptor.onLoad方法(如果有对应的Interceptor)。
将数据对象纳入二级缓存。
如果数据对象实现了LifeCycle接口,则调用数据对象的onLoad方法。
返回数据对象。
Hibernate的主键生成机制
1) assigned
主键由外部程序负责生成,无需Hibernate参与。
2) hilo
通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。
3) seqhilo
与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。
4) increment
主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
5) identity
采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。
6) sequence
采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。
7) native
由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式。
8) uuid.hex
由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键。
9) uuid.string
与uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些数据库中可能出现问题(如PostgreSQL)。
10) foreign
使用外部表的字段作为主键。一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适应性。
这10中生成OID标识符的方法,increment 比较常用,把标识符生成的权力交给Hibernate处理.但是当同时多个Hibernate应用操作同一个数据库,甚至同一张表的时候.就推荐使用identity 依赖底层数据库实现,但是数据库必须支持自动增长,当然针对不同的数据库选择不同的方法.如果你不能确定你使用的数据库具体支持什么的情况下.可以选择用native 让Hibernate来帮选择identity,sequence,或hilo.
另外由于常用的数据库,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用generator-class=native的主键生成方式。
不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成机制
Hibernate工作原理及为什么要用?
原理:
1. 读取并解析配置文件
2. 读取并解析映射信息,创建SessionFactory
3. 打开Sesssion
4. 创建事务Transation
5. 持久化操作
6. 提交事务
7. 关闭Session
8. 关闭SesstionFactory
为什么要用:
* 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
* Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
* hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
* hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
Hibernate是如何延迟加载?
* Hibernate2延迟加载实现:a)实体对象  b)集合(Collection)
* Hibernate3 提供了属性的延迟加载功能
当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
说下Hibernate的缓存机制
* 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存
* 二级缓存:
a)应用及缓存
b)分布式缓存
条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非              关键数据
c)  第三方缓存的实现
Hibernate的查询方式
Sql、Criteria,object comptosition
Hql:
* 属性查询
* 参数查询、命名参数查询
* 关联查询
* 分页查询
* 统计函数
Struts1工作机制?为什么要使用Struts?
工作机制:
Struts的工作流程:
在web应用启动时就会加载初始化ActionServlet,ActionServlet从struts-config.xml文件中读取配置信息,把它们存放到各种配置对象当ActionServlet接收到一个客户请求时,将执行如下流程.
(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;
(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中;
(3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法;
(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;
(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的Action实例不存在,就先创建这个实例,然后调用Action的execute()方法;
(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给ActionForward对象指向的JSP组件;
(7)ActionForward对象指向JSP组件生成动态网页,返回给客户;
为什么要用:
JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。
基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件
Struts的validate框架是如何验证的?
在struts配置文件中配置具体的错误提示,再在FormBean中的validate()方法具体调用。
说下Struts的设计模式
MVC模式:  web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config.xml 文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果 Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法。Execute()从 ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给 ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。
单例模式
Factory(工厂模式):
定义一个基类===》实现基类方法(子类通过不同的方法)===》定义一个工厂类(生成子类实例)
===》开发人员调用基类方法
Proxy(代理模式)
Spring mvc工作机制及为什么要用?
1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。
2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.
3.DispatcherServlet请请求提交到目标Controller
4.Controller进行业务逻辑处理后,会返回一个ModelAndView
5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
6.视图对象负责渲染返回给客户端。
为什么用:
AOP 让开发人员可以创建非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务   (比 如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。
IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。正如单词 倒置 所表明的,IOC 就像反      过来的。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用     其协作对象构造的。因此是由容器管理协作对象(collaborator)。
Spring即使一个AOP框架,也是一IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协作对象)。然后可以很容易地在需要时替换具有类似接口的协作对象。
、 Hibernate中的update()和saveOrUpdate()的区别
saveOrUpdate()方法可以实现update()的功能,但会多些步骤,具体如下:
如果对象在该session中已经被持久化,不进行操作;
对象的标识符属性(identifier property)在数据库中不存在或者是个暂时的值,调用save()方法保存它;
如果session中的另一个对象有相同的标识符抛出一个异常;
以上皆不符合则调用update()更新之。
Hibernate:怎么得到一个Collection的大小而不用初始化它?
Integer size = (Integer) s.createFilter( collection, "select count(*)" ).uniqueResult
Hibernate :怎么得到查询结果的记录数而不用返回查询结果?
Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult
缓存
Session的load/get方法,前者会使用二级缓存,而后者则不使用。

 Query和list/iterator,
 i. list只能利用查询缓存(但在交易系统中查询缓存作用不大),无法利用二级缓存中的单个实体,但list查出的对象会写入二级缓存,但它一般只生成较少的执行SQL语句,很多情况就是一条(无关联)。
ii. iterator则可以利用二级缓存,对于一条查询语句,它会先从数据库中找出所有符合条件的记录的ID,再通过ID去缓存找,对于缓存中没有的记录,再构造语句从数据库中查出,因此很容易知道,如果缓存中没有任何符合条件的记录,使用iterator会产生N+1条SQL语句(N为符合条件的记录数)
iii. 通过iterator,配合缓存管理API,在海量数据查询中可以很好的解决内存问题,如:
while(it.hasNext()){
YouObject object = (YouObject)it.next();
session.evict(youObject);
sessionFactory.evice(YouObject.class, youObject.getId());
}
如果用list方法,很可能就出OutofMemory错误了。
Hibernate 的应用(Hibernate 的结构)?
答://首先获得SessionFactory 的对象
SessionFactory sessionFactory = new Configuration().configure().
buildSessionFactory();
//然后获得session 的对象
Session session = sessionFactory.openSession();
//其次获得Transaction 的对象
Transaction tx = session.beginTransaction();
//执行相关的数据库操作:增,删,改,查
session.save(user); //增加, user 是User 类的对象
session.delete(user); //删除
session.update(user); //更新
Query query = session.createQuery(“from User”); //查询
List list = query.list();
//提交事务
tx.commit();
//如果有异常,我们还要作事务的回滚,恢复到操作之前
tx.rollback();
//最后还要关闭session,释放资源
session.close();
Hibernate 是如何处理事务的;
Hibernate 的事务实际上是底层的JDBC Transaction 的封装或者是JTA
Transaction 的封装;默认情况下使用JDBCTransaction。
Hibernate 有哪5 个核心接口
Configuration 接口:配置Hibernate,根据其启动hibernate,创建
SessionFactory 对象;
SessionFactory 接口:初始化Hibernate,充当数据存储源的代理,创建
session 对象,sessionFactory 是线程安全的,意味着它的同一个实例可以被应
用的多个线程共享,是重量级、二级缓存;
Session 接口:负责保存、更新、删除、加载和查询对象,是线程不安全的,
避免多个线程共享同一个session,是轻量级、一级缓存;
Transaction 接口:管理事务;
Query 和Criteria 接口:执行数据库的查询。
说下Hibernate的缓存机制
1. 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存
2. 二级缓存:
a) 应用及缓存
b) 分布式缓存
条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非        关键数据
c) 第三方缓存的实现
hibernate数据查询的几种方式
1.使用主键id加载对象(load(),get());
2.通过对象导航,比如通过stu.getTeam()得到team的实例;
3 使用hql;
4使用qbc(query by criteria)
5直接使用sql语句取得记录集;
一般都使用后面三种方式.
注意.hql是面向对象的查询.语法和sql是基本一样的.不区分大小写的,但是注意的是对与对象.必须遵循对象的大小写.因为hql是对像查询..同时我们必须清楚.hql只能取得对象,而不支持uid(update,insert.delete)
小结:
hql功能很强大,适合各种情况,但是动态条件查询构造起来很不方便.
criteria 最适合动态查询,但不太适合统计查询,qbe还不够强大.只适合简单的查询.
nativesql可以实现特定的数据库的sql.但是可移植性并不好.
针对web应用来说,大部分常规查询都是动态条件查询,所以首先criteria,并且h 3提供的detachedcriteria,可以在web层构造好detachedcriteria再进入session执行查询.但是涉及到统计查询和非常复杂的关联查询.criteria就无能为力了.这种情况下选择使用hql.最后如果涉及到使用某些数据库的特性的时候,就只有选择 nativesql了.
hql常用来进行实体检索.这个时候要注意返回的list中的元素是实体还是实体数组.如果hql进行实体属性查询,当查询两个以上的属性时,list中的元素就是属性数组了.
qbc最大的用途在与动态查询.它不会忽略配置文件中的预先抓取策略.
使用本地sql检索必须检索对象的所有属性.
Hibernate中:不看数据库,不看XML文件,不看查询语句,怎么样能知道表结构?
看表结构对应的类文件,比如UserInfo表对应的UserInfo.java文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值