Java Web 面试题

Jsp方面:

69、forward 和redirect的区别
答:forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
    redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
70、jsp有哪些内置对象?作用分别是什么?
答:JSP共有以下9种基本内置组件(可与ASP的6种内部组件相对应):
 request 用户端请求,此请求会包含来自GET/POST请求的参数
   response 网页传回用户端的回应
   pageContext 网页的属性是在这里管理
   session 与请求有关的会话期
   application servlet 正在执行的内容
   out 用来传送回应的输出
   config servlet的构架部件
   page JSP网页本身
   exception 针对错误网页,未捕捉的例外
71、jsp有哪些动作?作用分别是什么?
答:JSP共有以下6种基本动作
   jsp:include:在页面被请求的时候引入一个文件。
   jsp:useBean:寻找或者实例化一个JavaBean。
   jsp:setProperty:设置JavaBean的属性。
   jsp:getProperty:输出某个JavaBean的属性。
   jsp:forward:把请求转到一个新的页面。
   jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记
72、JSP中动态INCLUDE与静态INCLUDE的区别?
答:动态INCLUDE用jsp:include动作实现
   它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数
   静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面
   <%@ include file="included.htm" %>
73、两种跳转方式分别是什么?有什么区别?
答:有两种,分别为:
 
 
前者页面不会转向include所指的页面,只是显示该页的结果,主页面还是原来的页面。执行完后还会回来,相当于函数调用。并且可以带参数.后者完全转向新页面,不会再回来。相当于go to 语句。
74、JSP的内置对象及方法。
答:request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 
    response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等) 
    out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。 
    pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。 
    session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息 
    applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 
    config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 
    page表示从该页面产生的一个servlet实例

第五章 Servlet篇

75、说一说Servlet的生命周期?
答:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
76、JAVA SERVLET API中forward() 与redirect()的区别?
答:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。
77、Servlet的基本架构
答:
public class ServletName extends HttpServlet {
  public void doPost(HttpServletRequest request, HttpServletResponseresponse) throws
      ServletException, IOException  {
      }
  public void doGet(HttpServletRequest request, HttpServletResponseresponse) throws
      ServletException, IOException  {
      }
}

78、什么情况下调用doGet()和doPost()?
答:Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()。
79、servlet的生命周期
答:web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。
80、如何现实servlet的单线程模式
答:<%@ page isThreadSafe="false"%>
81、页面间对象传递的方法
答:request,session,application,cookie等
82、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么? 
答:JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
83、四种会话跟踪技术
答:会话作用域ServletsJSP 页面描述
page否是代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示。这既包括 servlet 又包括被编译成 servlet 的 JSP 页面
request是是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系)
session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求
application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域
84、Request对象的主要方法
答:
setAttribute(String name,Object):设置名字为name的request的参数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例
getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组
getCharacterEncoding():返回请求中的字符编码方式
getContentLength():返回请求的Body的长度
getHeader(String name):获得HTTP协议定义的文件头信息
getHeaders(String name):返回指定名字的request Header的所有值,结果是一个枚举的实例
getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例
getInputStream():返回请求的输入流,用于获得请求中的数据
getMethod():获得客户端向服务器端传送数据的方法
getParameter(String name):获得客户端传送给服务器端的有name指定的参数值
getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例
getParameterValues(String name):获得有name指定的参数的所有值
getProtocol():获取客户端向服务器端传送数据所依据的协议名称
getQueryString():获得查询字符串
getRequestURI():获取发出请求字符串的客户端地址
getRemoteAddr():获取客户端的IP地址
getRemoteHost():获取客户端的名字
getSession([Boolean create]):返回和请求相关Session
getServerName():获取服务器的名字
getServletPath():获取客户端所请求的脚本文件的路径
getServerPort():获取服务器的端口号
removeAttribute(String name):删除请求中的一个属性
85、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
答:
  Public String translate (String str) {
    String tempStr = "";
    try {
      tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
      tempStr = tempStr.trim();
    }
    catch (Exception e) {
      System.err.println(e.getMessage());
    }
    return tempStr;
  }
86、Servlet执行时一般实现哪几个方法?
答:
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()

Jdbc、Jdo篇

87、Class.forName的作用?为什么要用?
答:调用该访问返回一个以字符串指定类名的类的对象。
88、Jdo是什么?
答:JDO是Java对象持久化的新的规范,为javadata object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。
89、说出数据连接池的工作机制是什么?
答:J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。
90、Jdo是什么? 
答:JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。

Xml篇

91、xml有哪些解析技术?区别是什么?
答:有DOM,SAX,STAX等
DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问
STAX:Streaming API for XML (StAX)
92、你在项目中用到了xml技术的哪些方面?如何实现的?
答:用到了数据存贮,信息配置两方面。在做数据交换平台时,将不能数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中。
93、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式? 
答:a: 两种形式 dtd  schema,b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的),c:有DOM,SAX,STAX等 
    DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问
SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问 
STAX:Streaming API for XML (StAX)

94、用jdom解析xml文件时如何解决中文问题?如何解析?
答:看如下代码,用编码方式加以解决
package test;
import java.io.*;
public class DOMTest
{
private String inFile = "c:people.xml";
private String outFile = "c:people.xml";
public static void main(String args[])
{
new DOMTest();
}
public DOMTest()
{
try
{
javax.xml.parsers.DocumentBuilderbuilder =


javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.dom.Document doc =builder.newDocument();
org.w3c.dom.Element root =doc.createElement("老师");
org.w3c.dom.Element wang =doc.createElement("王");
org.w3c.dom.Element liu =doc.createElement("刘");
wang.appendChild(doc.createTextNode("我是王老师"));
root.appendChild(wang);
doc.appendChild(root);
javax.xml.transform.Transformertransformer =
javax.xml.transform.TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING,"gb2312");
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT,"yes");


transformer.transform(new javax.xml.transform.dom.DOMSource(doc),
new

javax.xml.transform.stream.StreamResult(outFile));
}
catch (Exception e)
{
System.out.println (e.getMessage());
}
}
}

95、编程用JAVA解析XML的方式.
答:用SAX方式解析XML,XML文件如下:

SAXHandler.java
import java.io.*;
import java.util.Hashtable;
import org.xml.sax.*;
public class SAXHandler extends HandlerBase
{
private Hashtable table = new Hashtable();
private String currentElement = null;
private String currentValue = null;
public void setTable(Hashtable table)
{
this.table = table;
}
public Hashtable getTable()
{
return table;
}
public void startElement(String tag, AttributeList attrs)
throws SAXException
{
currentElement = tag;
}
public void characters(char[] ch, int start, int length)
throws SAXException
{
currentValue = new String(ch, start, length);
}
public void endElement(String name) throws SAXException
{
if (currentElement.equals(name))
table.put(currentElement, currentValue);
}

 

第六章 应用服务器篇

106、如何给weblogic指定大小的内存? 
答:在启动Weblogic的脚本中(位于所在Domian对应服务器目录下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以调整最小内存为32M,最大200M
EJB需直接实现它的业务接口或Home接口吗,请简述理由。
远程接口和Home接口不需要直接实现,他们的实现代码是由服务器产生的,程序运行中对应实现类会作为对应接口类型的实例被使用。
107、应用服务器有那些?
答:BEA WebLogic Server,IBM WebSphere Application Server,Oracle9i Application Server,jBoss,Tomcat
108、如何设定的weblogic的热启动模式(开发模式)与产品发布模式?
答:可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件,增加set PRODUCTION_MODE=true。
109、如何启动时不需输入用户名与密码?
答:修改服务启动文件,增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.
110、在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中?
答:保存在此Domain的config.xml文件中,它是服务器的核心配置文件。
111、说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入 http://主机:端口号//helloword.jsp就可以看到运行结果了?  又比如这其中用到了一个自己写的javaBean该如何办?
答:Domain目录服务器目录applications,将应用目录放在此目录下将可以作为应用访问,如果是Web应用,应用目录需要满足Web应用目录要求,jsp文件可以直接放在应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,设置服务器的缺省应用将可以实现在浏览器上无需输入应用名。
112、在weblogic中发布ejb需涉及到哪些配置文件
答:不同类型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml 
86、如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置
缺省安装中使用DemoIdentity.jks和DemoTrust.jks  KeyStore实现SSL,需要配置服务器使用Enable SSL,配置其端口,在产品模式下需要从CA获取私有密钥和数字证书,创建identity和trust keystore,装载获得的密钥和数字证书。可以配置此SSL连接是单向还是双向的。
113、如何查看在weblogic中已经发布的EJB?
答:可以使用管理控制台,在它的Deployment中可以查看所有已发布的EJB
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过来,而non-persistent方式的消息将被丢弃

第七章 J2EE,MVC篇

114、MVC的各个部分都有那些技术来实现?如何实现?
答:MVC是Model-View-Controller的简写。"Model"代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表示面(由JSP页面产生),"Controller" 是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。
115、J2EE是什么?
答:Je22是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中,可按照功能划分为不同的组件,这些组件又可在不同计算机上,并且处于相应的层次(tier)中。所属层次包括客户层(clietntier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。
116、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。
答:Web Service描述语言WSDL
SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。
UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
117、J2EE是技术还是平台还是框架?
答:J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。
 J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。
118、STRUTS的应用(如STRUTS架构)
答:Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能:
一.包含一个controller servlet,能将用户的请求发送到相应的Action对象。
二.JSP自由tag库,并且在controllerservlet中提供关联支持,帮助开发员创建交互式表单应用。
三.提供了一系列实用对象:XML处理、通过Javareflection APIs自动处理JavaBeans属性、国际化的提示和消息。
119、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 
答:Web ServiceWeb Service是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼容的组件进行互操作。
JAXP(Java API for XML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口,当你需要改变具体的实现时候也不需要修改代码。
JAXM(Java API for XML Messaging) 是为SOAP通信提供访问方法和传输机制的API。
WSDL是一种 XML 格式,用于将网络服务描述为一组端点,这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述,然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点(服务)。
SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。 
UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
120、C/S 与 B/S 区别:
答:有如下八个方面的不同:
1.硬件环境不同: 
  C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.
  B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行 
2.对安全要求不同 
  C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.
  B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。
3.对程序架构不同 
  C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.
  B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟. 
4.软件重用不同 
  C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.
  B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子 
5.系统维护不同  
  C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统
  B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级. 
6.处理问题不同 
  C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统
  B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小. 
7.用户接口不同 
  C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
  B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本. 
8.信息流不同 
  C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低
  B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更像交易中心。
121、什么是web容器
答:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接更容器中的环境变量接**互,不必关注其它系统问题。主要有WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。122、什么是EJB容器
答:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理
123、什么是JNDI
答:(Java Naming & Directory Interface)JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。
124、什么是JMS
答:(Java Message Service)JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。
125、什么是JTA
答:(Java Transaction API)JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。
126、什么是JAF
答:(Java Action FrameWork)JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。
RMI/IIOP:(Remote Method Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。
127、MVC的各个部分都有那些技术来实现?如何实现? 
答:MVC是Model-View-Controller的简写。"Model" 代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表示面(由JSP页面产生),"Controller" 是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。

第八章 设计模式方面篇

128、开发中都用到了那些设计模式?用在什么场合?
答:每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心。通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。
129、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法
答:Session Facade Pattern:使用SessionBean访问EntityBean
Message Facade Pattern:实现异步调用
EJB Command Pattern:使用Command JavaBeans取代SessionBean,实现轻量级访问
Data Transfer Object Factory:通过DTO Factory简化EntityBean数据提供特性
Generic Attribute Access:通过AttibuteAccess接口简化EntityBean数据提供特性
Business Interface:通过远程(本地)接口和Bean类实现相同接口规范业务逻辑一致性
EJB架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂,项目队伍越庞大则越能体现良好设计的重要性。
130、j2ee常用的设计模式?说明工厂模式。
 答:Java中的23种设计模式:
Factory(工厂模式),      Builder(建造模式),       Factory Method(工厂方法模式),
Prototype(原始模型模式),Singleton(单例模式),    Facade(门面模式),
Adapter(适配器模式),    Bridge(桥梁模式),        Composite(合成模式),
Decorator(装饰模式),    Flyweight(享元模式),     Proxy(代理模式),
Command(命令模式),      Interpreter(解释器模式), Visitor(访问者模式),
Iterator(迭代子模式),   Mediator(调停者模式),    Memento(备忘录模式),
Observer(观察者模式),   State(状态模式),         Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

第九章 Hibernate程序性能优化篇

 

  本文依照HIBERNATE帮助文档,一些网络书籍及项目经验整理而成,只提供要点和思路,具体做法可以留言探讨,或是找一些更详细更有针对性的资料。

  初用HIBERNATE的人也许都遇到过性能问题,实现同一功能,用HIBERNATE与用JDBC性能相差十几倍很正常,如果不及早调整,很可能影响整个项目的进度。

  大体上,对于HIBERNATE性能调优的主要考虑点如下:

  Ø 数据库设计调整

  Ø HQL优化

  Ø API的正确使用(如根据不同的业务类型选用不同的集合及查询API)

  Ø 主配置参数(日志,查询缓存,fetch_size, batch_size等)

  Ø 映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)

  Ø 一级缓存的管理

  Ø 针对二级缓存,还有许多特有的策略

  Ø 事务控制策略。

  1、 数据库设计

  a) 降低关联的复杂性

  b) 尽量不使用联合主键

  c) ID的生成机制,不同的数据库所提供的机制并不完全一样

  d) 适当的冗余数据,不过分追求高范式

  2、 HQL优化

  HQL如果抛开它同HIBERNATE本身一些缓存机制的关联,HQL的优化技巧同普通的SQL优化技巧一样,可以很容易在网上找到一些经验之谈。

  3、 主配置

  a) 查询缓存,同下面讲的缓存不太一样,它是针对HQL语句的缓存,即完全一样的语句再次执行时可以利用缓存数据。但是,查询缓存在一个交易系统(数据变更频繁,查询条件相同的机率并不大)中可能会起反作用:它会白白耗费大量的系统资源但却难以派上用场。

  b) fetch_size,同JDBC的相关参数作用类似,参数并不是越大越好,而应根据业务特征去设置

  c) batch_size同上。

  d) 生产系统中,切记要关掉SQL语句打印。

  4、 缓存

  a) 数据库级缓存:这级缓存是最高效和安全的,但不同的数据库可管理的层次并不一样,比如,在ORACLE中,可以在建表时指定将整个表置于缓存当中。

  b) SESSION缓存:在一个HIBERNATE SESSION有效,这级缓存的可干预性不强,大多于HIBERNATE自动管理,但它提供清除缓存的方法,这在大批量增加/更新操作是有效的。比如,同时增加十万条记录,按常规方式进行,很可能会发现OutofMemeroy的异常,这时可能需要手动清除这一级缓存:Session.evict以及Session.clear

  c) 应用缓存:在一个SESSIONFACTORY中有效,因此也是优化的重中之重,因此,各类策略也考虑的较多,在将数据放入这一级缓存之前,需要考虑一些前提条件:

  i. 数据不会被第三方修改(比如,是否有另一个应用也在修改这些数据?)

  ii. 数据不会太大

  iii. 数据不会频繁更新(否则使用CACHE可能适得其反)

  iv. 数据会被频繁查询

  v. 数据不是关键数据(如涉及钱,安全等方面的问题)。

  缓存有几种形式,可以在映射文件中配置:read-only(只读,适用于很少变更的静态数据/历史数据),nonstrict-read-write,read-write(比较普遍的形式,效率一般),transactional(JTA中,且支持的缓存产品较少)

  d) 分布式缓存:同c)的配置一样,只是缓存产品的选用不同,在目前的HIBERNATE中可供选择的不多,oscache, jboss cache,目前的大多数项目,对它们的用于集群的使用(特别是关键交易系统)都持保守态度。在集群环境中,只利用数据库级的缓存是最安全的。

  5、 延迟加载

  a) 实体延迟加载:通过使用动态代理实现

  b) 集合延迟加载:通过实现自有的SET/LIST,HIBERNATE提供了这方面的支持

  c) 属性延迟加载:

  6、 方法选用

  a) 完成同样一件事,HIBERNATE提供了可供选择的一些方式,但具体使用什么方式,可能用性能/代码都会有影响。显示,一次返回十万条记录(List/Set/Bag/Map等)进行处理,很可能导致内存不够的问题,而如果用基于游标(ScrollableResults)或Iterator的结果集,则不存在这样的问题。

  b) Session的load/get方法,前者会使用二级缓存,而后者则不使用。

  c) Query和list/iterator,如果去仔细研究一下它们,你可能会发现很多有意思的情况,二者主要区别(如果使用了Spring,在HibernateTemplate中对应find,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错误了。

  iv. 通过上面的说明,我想你应该知道如何去使用这两个方法了。

  7、 集合的选用

  在HIBERNATE 3.1文档的“19.5. Understanding Collection performance”中有详细的说明。

  8、 事务控制

  事务方面对性能有影响的主要包括:事务方式的选用,事务隔离级别以及锁的选用

  a) 事务方式选用:如果不涉及多个事务管理器事务的话,不需要使用JTA,只有JDBC的事务控制就可以。

  b) 事务隔离级别:参见标准的SQL事务隔离级别

  c) 锁的选用:悲观锁(一般由具体的事务管理器实现),对于长事务效率低,但安全。乐观锁(一般在应用级别实现),如在HIBERNATE中可以定义VERSION字段,显然,如果有多个应用操作数据,且这些应用不是用同一种乐观锁机制,则乐观锁会失效。因此,针对不同的数据应有不同的策略,同前面许多情况一样,很多时候我们是在效率与安全/准确性上找一个平衡点,无论如何,优化都不是一个纯技术的问题,你应该对你的应用和业务特征有足够的了解。

  9、 批量操作

  即使是使用JDBC,在进行大批数据更新时,BATCH与不使用BATCH有效率上也有很大的差别。我们可以通过设置batch_size来让其支持批量操作。

  举个例子,要批量删除某表中的对象,如“delete Account”,打出来的语句,会发现HIBERNATE找出了所有ACCOUNT的ID,再进行删除,这主要是为了维护二级缓存,这样效率肯定高不了,在后续的版本中增加了bulk delete/update,但这也无法解决缓存的维护问题。也就是说,由于有了二级缓存的维护问题,HIBERNATE的批量操作效率并不尽如人意!

  从前面许多要点可以看出,很多时候我们是在效率与安全/准确性上找一个平衡点,无论如何,优化都不是一个纯技术的问题,你应该对你的应用和业务特征有足够的了解,一般的,优化方案应在架构设计期就基本确定,否则可能导致没必要的返工,致使项目延期,而作为架构师和项目经理,还要面对开发人员可能的抱怨,必竟,我们对用户需求更改的控制力不大,但技术/架构风险是应该在初期意识到并制定好相关的对策。

  还有一点要注意,应用层的缓存只是锦上添花,永远不要把它当救命稻草,应用的根基(数据库设计,算法,高效的操作语句,恰当API的选择等)才是最重要的。

 

 

Hibernate程序性能优化

http://www.weaseek.com  2008-08-1911:21:35  来源:搜讯社区

初用HIBERNATE的人也许都遇到过性能问题,实现同一功能,用HIBERNATE与用JDBC性能相差十几倍很正常,如果不及早调整,很可能影响整个项目的进度。

本文依照HIBERNATE帮助文档,一些网络书籍及项目经验整理而成,只提供要点和思路,具体做法可以探讨,或是找一些更详细更有针对性的资料。

初用HIBERNATE的人也许都遇到过性能问题,实现同一功能,用HIBERNATE与用JDBC性能相差十几倍很正常,如果不及早调整,很可能影响整个项目的进度。

大体上,对于HIBERNATE性能调优的主要考虑点如下:

Ø 数据库设计调整

Ø HQL优化

Ø API的正确使用(如根据不同的业务类型选用不同的集合及查询API)

Ø 主配置参数(日志,查询缓存,fetch_size, batch_size等)

Ø 映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)

Ø 一级缓存的管理

Ø 针对二级缓存,还有许多特有的策略

Ø 事务控制策略。

1、数据库设计

a) 降低关联的复杂性

b) 尽量不使用联合主键

c) ID的生成机制,不同的数据库所提供的机制并不完全一样

d) 适当的冗余数据,不过分追求高范式

2、 HQL优化

HQL如果抛开它同HIBERNATE本身一些缓存机制的关联,HQL的优化技巧同普通的SQL优化技巧一样,可以很容易在网上找到一些经验之谈。

3、主配置

a) 查询缓存,同下面讲的缓存不太一样,它是针对HQL语句的缓存,即完全一样的语句再次执行时可以利用缓存数据。但是,查询缓存在一个交易系统(数据变更频繁,查询条件相同的机率并不大)中可能会起反作用:它会白白耗费大量的系统资源但却难以派上用场。

b) fetch_size,同JDBC的相关参数作用类似,参数并不是越大越好,而应根据业务特征去设置

c) batch_size同上。

d) 生产系统中,切记要关掉SQL语句打印。

4、缓存

a) 数据库级缓存:这级缓存是最高效和安全的,但不同的数据库可管理的层次并不一样,比如,在ORACLE中,可以在建表时指定将整个表置于缓存当中。

b) SESSION缓存:在一个HIBERNATE SESSION有效,这级缓存的可干预性不强,大多于HIBERNATE自动管理,但它提供清除缓存的方法,这在大批量增加/更新操作是有效的。比如,同时增加十万条记录,按常规方式进行,很可能会发现OutofMemeroy的异常,这时可能需要手动清除这一级缓存:Session.evict以及 Session.clear

c) 应用缓存:在一个SESSIONFACTORY中有效,因此也是优化的重中之重,因此,各类策略也考虑的较多,在将数据放入这一级缓存之前,需要考虑一些前提条件:

i. 数据不会被第三方修改(比如,是否有另一个应用也在修改这些数据?)

ii. 数据不会太大

iii. 数据不会频繁更新(否则使用CACHE可能适得其反)

iv. 数据会被频繁查询

v. 数据不是关键数据(如涉及钱,安全等方面的问题)。

缓存有几种形式,可以在映射文件中配置:read-only(只读,适用于很少变更的静态数据/历史数据),nonstrict-read-write,read-write(比较普遍的形式,效率一般),transactional(JTA中,且支持的缓存产品较少)

d) 分布式缓存:同c)的配置一样,只是缓存产品的选用不同,在目前的HIBERNATE中可供选择的不多,oscache,jboss cache,目前的大多数项目,对它们的用于集群的使用(特别是关键交易系统)都持保守态度。在集群环境中,只利用数据库级的缓存是最安全的。

 

Hibernate 优化

一。 inverse = ?
inverse=false(default)
用于单向one-to-many关联
parent.getChildren().add(child) // insert child
parent.getChildren().delete(child) // delete child
inverse=true
用于双向one-to-many关联
child.setParent(parent); session.save(child) // insert child
session.delete(child)
在分层结构的体系中
parentDao, childDao对于CRUD的封装导致往往直接通过session接口持久化对象,而很少通过关联对象可达性
二。 one-to-many关系
单向关系还是双向关系?
parent.getChildren().add(child)对集合的触及操作会导致lazy的集合初始化,在没有对集合配置二级缓存的情况下,应避免此类操作
select * from child where parent_id = xxx;
性能口诀:
1. 一般情况下避免使用单向关联,尽量使用双向关联
2. 使用双向关联,inverse=“true”
3. 在分层结构中通过DAO接口用session直接持久化对象,避免通过关联关系进行可达性持久化


三。many-to-one关系
单向many-to-one表达了外键存储方
灵活运用many-to-one可以避免一些不必要的性能问题
many-to-one表达的含义是:0..n : 1,many可以是0,可以是1,也可以是n,也就是说many-to-one可以表达一对多,一对一,多对一关系
因此可以配置双向many-to-one关系,例如:
1. 一桌四人打麻将,麻将席位和打麻将的人是什么关系?是双向many-to-one的关系

四。one-to-one
通过主键进行关联
相当于把大表拆分为多个小表
例如把大字段单独拆分出来,以提高数据库操作的性能
Hibernate的one-to-one似乎无法lazy,必须通过bytecode enhancement

五。集合List/Bag/Set
one-to-many
1. List需要维护index column,不能被用于双向关联,必须inverse=“false”,被谨慎的使用在某些稀有的场合

2. Bag/Set语义上没有区别
3. 我个人比较喜欢使用Bag
many-to-many
1. Bag和Set语义有区别
2。 建议使用Set

六。集合的过滤
1. children = session.createFilter(parent.getChildren(), “where this.age > 5and this.age < 10”).list()
针对一对多关联当中的集合元素非常庞大的情况,特别适合于庞大集合的分页:
session.createFilter(parent.getChildren(),“”).setFirstResult(0).setMaxResults(10).list();
在hibernate 中用super.getSession().createFilter( , )

七。继承关系当中的隐式多态
HQL: from Object
1. 把所有数据库表全部查询出来
2. polymorphism=“implicit”(default)将当前对象,和对象所有继承子类全部一次性取出
3. polymorphism=“explicit”,只取出当前查询对象

八。Hibernate二级缓存
著名的n+1问题:from Child,然后在页面上面显示每个子类的父类信息,就会导致n条对parent表的查询:
select * from parent where id = ?
.......................
select * from parent where id = ?
解决方案
1. eager fetch
2. 二级缓存

九。inverse和二级缓存的关系
当使用集合缓存的情况下:
1. inverse=“false”,通过parent.getChildren()来操作,Hibernate维护集合缓存
2. inverse=“true”,直接对child进行操作,未能维护集合缓存!导致缓存脏数据
3. 双向关联,inverse=“true”的情况下应避免使用集合缓存

十。Hibernate二级缓存是提升web应用性能的法宝
OLTP类型的web应用,由于应用服务器端可以进行群集水平扩展,最终的系统瓶颈总是逃不开数据库访问;

哪个框架能够最大限度减少数据库访问,降低数据库访问压力, 哪个框架提供的性能就更高;针对数据库的缓存策略:
1. 对象缓存:细颗粒度,针对表的记录级别,透明化访问,在不改变程序代码的情况下可以极大提升web应用的性能。对象缓存是ORM的制胜法宝。
2. 对象缓存的优劣取决于框架实现的水平,Hibernate是目前已知对象缓存最强大的开源ORM
3. 查询缓存:粗颗粒度,针对查询结果集,应用于数据实时化要求不高的场合

十一。应用场合决定了系统架构
一、是否需要ORM
Hibernate or iBATIS?
二、采用ORM决定了数据库设计
Hibernate:
倾向于细颗粒度的设计,面向对象,将大表拆分为多个关联关系的小表,消除冗余column,通过二级缓存提升性能(DBA比较忌讳关联关系的出现,但是ORM的缓存将突破关联关系的性能瓶颈);Hibernate的性能瓶颈不在于关联关系,而在于大表的操作
iBATIS:
倾向于粗颗粒度设计,面向关系,尽量把表合并,通过表column冗余,消除关联关系。无有效缓存手段。iBATIS的性能瓶颈不在于大表操作,而在于关联关系。

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


最近开始留意项目中的Hibernate的性能问题,希望可以抽出时间学习一下hiberante的性能优化。主要是对数据库连接池技术、hibernate二级缓存、hibernate的配置优化等问题进行学习!


1.关联关系:
普通的关联关系:是不包括一个连接表,也就是中间表如:
create table Person(personId bigint not null primary key,addressId bigint notnull)
create table Address(addressId bigint not null primary key)
也就是不会还有一个关系表如:
create table Person(personId bigint not null primary key)
create table Address(addressId bigint not null primary key)
create table PersonAddress(personId bigint not null,ddressId bigint not nullprimary key)


单向many-to-one关联是最常见的,而单向one-to-many是不常见的


2. inner join(内连接)
left (outer) join(左外连接)
right (outer) join (右外连接)
full join (全连接,并不常用)


3.小技巧:
统计结果数目:
(Integer)session.iterator("select count(*) from..").next()).intValue();
根据一个集合大小来排序:
select user.id,user.name
from User as user.name
left join user.messages msg
group by user.id,user.name
having count(msg)>=1

 

-

 

 

Hibernate优化的几点建议

关键字: hibernate 优化 ssh

优化hibernate性能的几点建议

1、针对oracle数据库而言,Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数,一般设置为30、50、100。Oracle数据库的JDBC驱动默认的FetchSize=15,设置Fetch Size设置为:30、50,性能会有明显提升,如果继续增大,超出100,性能提升不明显,反而会消耗内存。

  即在hibernate配制文件中进行配制:

1 <propertyname="hibernateProperties">
2 <props>
3 <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
4 <prop key="hibernate.show_sql">false</prop>
5 <!-- Create/update the database tablesautomatically when the JVM starts up
6 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
7 <!-- Turn batching off for better errormessages under PostgreSQL
8 <propkey="hibernate.jdbc.batch_size">100</prop> -->
9 <propkey="hibernate.jdbc.batch_size">50</prop>
10 </props>
11 </property>Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。
  2、如果是超大的系统,建议生成htm文件。加快页面提升速度。

  3、不要把所有的责任推在hibernate上,对代码进行重构,减少对数据库的操作,尽量避免在数据库查询时使用in操作,以及避免递归查询操作,代码质量、系统设计的合理性决定系统性能的高低。

  4、 对大数据量查询时,慎用list()或者iterator()返回查询结果,

  (1). 使用List()返回结果时,Hibernate会所有查询结果初始化为持久化对象,结果集较大时,会占用很多的处理时间。

  (2). 而使用iterator()返回结果时,在每次调用iterator.next()返回对象并使用对象时,Hibernate才调用查询将对应的对象初始化,对于大数据量时,每调用一次查询都会花费较多的时间。当结果集较大,但是含有较大量相同的数据,或者结果集不是全部都会使用时,使用iterator()才有优势。

  5、在一对多、多对一的关系中,使用延迟加载机制,会使不少的对象在使用时方会初始化,这样可使得节省内存空间以及减少数据库的负荷,而且若PO中的集合没有被使用时,就可减少互数据库的交互从而减少处理时间。

  6、对含有关联的PO(持久化对象)时,若default-cascade="all"或者 “save-update”,新增PO时,请注意对PO中的集合的赋值操作,因为有可能使得多执行一次update操作。

  7、 对于大数据量新增、修改、删除操作或者是对大数据量的查询,与数据库的交互次数是决定处理时间的最重要因素,减少交互的次数是提升效率的最好途径,所以在开发过程中,请将show_sql设置为true,深入了解Hibernate的处理过程,尝试不同的方式,可以使得效率提升。尽可能对每个页面的显示,对数据库的操作减少到100----150条以内。越少越好。

  以上是在进行struts+hibernate+spring进行项目开发中,对hibernate性能优化的几点心得

 

 

 

Hibernate性能优化

Java /juxinsishui 发表于2006-08-28, 18:26

 有很多人认为Hibernate天生效率比较低,确实,在普遍情况下,需要将执行转换为SQL语句的Hibernate的效率低于直接JDBC存取,然而,在经过比较好的性能优化之后,Hibernate的性能还是让人相当满意的,特别是应用二级缓存之后,甚至可以获得比较不使用缓存的JDBC更好的性能,下面介绍一些通常的Hibernate的优化策略:
    1.抓取优化
    抓取是指Hibernate如何在关联关系之间进行导航的时候,Hibernate如何获取关联对象的策略,其主要定义了两个方面:如何抓取和何时抓取
    1)如何抓取。
    Hibernate3主要有两种种抓取方式,分别应用于对象关联实例(many-to-one、one-to-one)和对象关联集合(set、map等),总共是四种变种
    JOIN抓取: 通过在SELECT语句中使用OUTER JOIN来获得对象的关联实例或者关联集合)
    SELECT抓取: 另外发送一条SELECT语句来抓取当前对象的关联实体和集合
    在我的开发经历中,此处对性能的优化是比较有限的,并不值得过多关注
    例:
    A.应用于对象关联实例(默认是false)
     
    B.应用于对象关联集合(默认是auto)
    
       ....
    
    2)何时抓取
    主要分为延迟加载和立即抓取,默认的情况下Hibernate3对对象关联实采用延迟加载,普通属性采用立即抓取,通过延迟加载和采用适当的抓取粒度,与不采用优化相比往往可以将性能提升数倍
    立即抓取:当抓取宿主对象时,同时抓取其关联对象和关联集以及属性
    延迟加载:当抓取宿主对象时,并不抓取其关联对象,而是当对其对象进行调用时才加载
    例:
    A.应用于对象关联实例(默认是延迟加载)
     
    B.应用于对象关联集合(默认是延迟加载)
    
       ....
    
    对于延迟加载,需要注意的时,对延迟对象的使用必须在Session关闭之前进行,Hibernate的LazyInitalizationException往往就是由于在Session的生命期外使用了延迟加载的对象。当我们进行Web开发时,可以使用OpenSessionInView模式,当请求开始时打开session,当请求响应结束时才关闭session,不过,在使用OpenSessionInView模式时,需要注意如果响应时间比较长(业务比较复杂或者客户端是低速网络),将Session资源(也就是数据库的连接)占用太久的话可以会导致资源耗尽
    3)抓取粒度
    抓取粒度指的是对象在关联关系之间被导航时一次预先加载的数量,Hibernate程序的性能比较差往往就在于没有对抓取粒度仔细考虑,当加载一个列表并在列表中的每个对象中对其关联进行导航时,往往导致N+1条SQL语句查询。
    例:
    A.应用于对象关联实例(默认为1),注意,对对象关联实例的设置是在被关联的对象之上的,譬如
    class User
    {
        Group g;
    }
    那么抓取粒度应该在Group的配置文件之上,见下
    
        ...
    
    对该值并没有一个约定俗成的值,根据情况而定,如果被关联表数据比较少,则可以设置地小一些,3-20,如果比较大则可以设到30-50,注意的时候,并不是越多越好,当其值超过50之后,对性能并没有多大改善但却无谓地消耗内存
    假设有如下例子:
       List users = query.list();
    如果有20个User,并对这20个User及其Group进行遍历,如果不设置batch-size(即batch-size="1"),则在最糟糕的情况
    下,需要1 + 20条SQL语句,如果设置batch-size="10",则最好的情况下只需要1 + 2条SQL语句
    B.应用于对象关联集合(默认为1)
    
       ....
    
    2.二级缓存
    Hibernate对数据的缓存包括两个级:一级缓存,在Session的级别上进行,主要是对象缓存,以其id为键保存对象,在Session的生命期间存在;二级缓存,在SessionFactory的级别上进行,有对象缓存和查询缓存,查询缓存以查询条件为键保存查询结果,在SessionFactory的生命期间存在。默认地,Hibernate只启用一级缓存,通过正确地使用二级缓存,往往可以获得意想不到的性能。
    1)对象缓存:
    当抓取一个对象之后,Hiberate将其以id为键缓存起来,当下次碰到抓取id相同的对象时,可以使用如下配置
    方法1:在缓存对象上配置
    
       
    
    useage表示使用什么类型的缓存,譬如只读缓存、读写缓存等等(具体参见Hibernate参考指南),值得注意的时,有部分缓存在Hibernate的实现中不支持读写缓存,譬如JBossCache在Hibernate的实现中只是一种只读缓存,具体缓存实现对缓存类型的支持情况,可以参见org.hibernate.cache包
    regions表示缓存分块,大部分的缓存实现往往对缓存进行分块,该部分是可选的,详细参见各缓存实现
    方法2:在hibernate.cfg.xml中配置
    
    我认为第二种更好,可以统一管理
    2)查询缓存
    查询时候将查询结果以查询条件为键保存起来,需要配置如下
    A.在hibernate.cfg.xml中配置(启用查询缓存)
    true  (前面的属性名可参见常量
org.hibernate.cfg.Enviroment.USE_QUERY_CACHE)
    B.程序
    query.setCacheable(true);
    query.setCacheRegions(...);
    需要注意的是,查询缓存与对象缓存要结合更有效,因为查询缓存仅缓存查询结果列表的主键数据
    一般情况下在开发中,对一些比较稳定而又被频繁引用的数据,譬如数据字典之类的,将其进行二级缓存,对一些查询条件和查询数据变化不频繁而又常常被使用的查询,将其进行二级缓存。由于二级缓存是放在内存中,而且Hibernate的缓存不是弱引用缓存(WeekReference),所以注意不要将大块的数据放入其中,否则可能会被内存造成比较大的压力。
    3.批量数据操作
    当进行大批量数据操作(几万甚至几十几百万)时,需要注意两点,一,批量提交,二,及时清除不需要的一级缓存数据
    1)所谓的批量提交,就是不要频繁使用session的flush,每一次进行flush,Hibernate将PO数据于数据库进行同步,对于海量级数据操作来说是性能灾难(同时提交几千条数据和提交一条数据flush一次性能差别可能会是几十倍的差异)。一般将数据操作放在事务中,当事务提交时Hibernate自动帮你进行flush操作。
    2)及时清除不需要的一级缓存数据:由于Hibernate默认采用一级缓存,而在session的生命期间,所有数据抓取之后会放入一级缓存中,而当数据规模比较庞大时,抓取到内存中的数据会让内存压力非常大,一般分批操作数据,被一次操作之后将一级缓存清除,譬如
    session.clear(User.class)
    4.杂项
    dynamic-insert,dynamic-update,动态插入和动态更新,指的是让Hibernate插入数据时仅插入非空数据,当修改数据时只修改变化的数据,譬如对于 
    class User
    {
       id
       username
       password
    }
    如果u.id=1, u.username="ayufox",u.password=null,那么如果不设置动态插入,则其sql语句是insert into users(id, username, password) values (1, 'ayufox', '),如果设置则其sql语句是insert into users(username) valeus('ayufox')
    在如上的情况下,如果修改u.password='11',那么如果不设置动态更新,则sql语句为update users set username='ayufox', password='11' where id = 1,如果设置则为update user set password='11' where d = 1
    设置是在class的映射文件中,如下
    
    
  该设置对性能的提升比较有限

 

你可能感兴趣的:(java,web,hibernate,servlet,数据库,jsp)