标签:基于 代理类 应对 mic 持久化 网络 搜索 apache 变更
XML技术用于数据存储、信息配置、数据交换三方面。
可以将数据存储在XML中,通过节点、元素内容、属性标示数据内容及关系。
可以使用XML很方便的做信息配置,软件的各种配置参数和对象关系都存贮在XML文件中。
在做数据交换平台时,将数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。
XML DTD(功能有限)
XML Schema (功能强大)
Schema本身是XML的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的),Schema支持命名空间,Schema支持数据类型,并且支持自定义数据类型,功能更完善,更强大,提供了无限的可扩展性。而且Schema是W3C的标准。
有DOM、SAX等。
DOM:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种标准方式。
DOM中的核心概念就是节点。DOM在分析XML文档时,将组成XML文档的各个部分(元素、属性、文本、注释和处理指令等)映射成一个对象,这个对象就叫做节点。在内存中,这些节点形成一颗文档树。整棵树势一个节点,树中的每一个节点也是一颗树(子树),我们通过访问树中的节点来存取XML文档的内容。由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像SAX那样是一次性的处理。DOM使用起来也要简单得多。
DOM的优点是使用比较灵活,缺点是需要将整个文档加载到内存,对内存消耗比较大。
SAX(simple api for xml)基于事件.
SAX是基于事件驱动的工作方式,顺序读取XML文件,当遇到文件开头,结束,
或标签开头和结束时,会触发一个事件。在读xml的过程会不断抛出对象作为事件参数抛出.在SAX中只能读,不能写,而且只读一次,其优点是对内存消耗较小.
XML常用解析API有JAXP、JDOM、Dom4j等。
JAXP是Java API for XML Processing的英文字头缩写,中文含义是:用于XML文档处理的使用Java语言编写的编程接口。由于问题太多,从JDK1.7开始删除该功能。不推荐使用。
JDOM是最早期很多人使用的一个第三方工具包,它提供了一些简单的方法解析XML。JDOM里面大部分是抽象类和类。
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件的XML解析都是采用的Dom4j,例如Struts、Hibernate和Spring。
现阶段最优雅最流行的解析XML的API就是Dom4j.
Html&JavaScript&Ajax部分的面试题,可能覆盖Html、JavaScript、Ajax等相关内容,这些知识基本都可通过《疯狂Ajax讲义》一书找到详细解答。
这部分面试题大部分从网络收集、整理,也有部分题目来自疯狂软件学员面试之后的反馈。
<input type="text" id="d1" onblur=" chkNumber (this)"/>
<script type=”text/javascript” />
function chkNumber(eleText)
{
var value = eleText.value;
var len = value.length;
for(var i=0;i<len;i++)
{
if(value.charAt(i)>"9" || value.charAt(i)<"0")
{
alert("含有非数字字符");
eleText.focus();
break;
}
}
}
</script>
Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写。
Ajax 尝试建立桌面应用程序的功能和交互性,与不断更新的 Web 应用程序之间的桥梁。不需要刷新页面就可以将请求提交到后台,用户根本感觉不到页面在发送请求或是交换数据.
Ajax 提供将笨拙的 Web 界面转化成能迅速响应的 Ajax 应用程序。
下面是 Ajax 应用程序所用到的基本技术:
HTML 用于建立 Web 表单并确定应用程序其他部分使用的字段。
JavaScript 代码是运行 Ajax 应用程序的核心代码,帮助改进与服务器应用程序的通信。
DHTML 或 Dynamic HTML,用于动态更新表单。
我们将使用div、span和其他动态 HTML 元素来标记 HTML。
文档对象模型 DOM 用于(通过 JavaScript 代码)处理 HTML 结构和(某些情况下)服务器返回的 XMLXMLHttpRequest 对象XML
Ajax的核心对象是XMLXMLHttpRequest 对象。
XMLHttpRequest提供不重新加载页面的情况下更新网页,在页面加载后在客户端向服务器请求数据,在页面加载后在服务器端接受数据,在后台向客户端发送数据。XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和GET 请求的能力。XMLHttpRequest 可以同步或异步返回 Web 服务器的响应,并且能以文本或者一个 DOM 文档形式返回内容。尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用:它可以接收任何形式的文本文档。
Javascript是使用UTF-8国际编码,即每个汉字用4个字节来存储,这就造成了用AJAX来send数据的时候出现会乱码。
Ajax乱码产生主要有2个原因
1. XMLHttpRequest返回的数据默认的字符编码是UTF-8,如果前台页面是gb2312或者其它编码数据就会产生乱码。
2. post方法提交数据默认的字符编码是UTF-8,如果后台是gb2312或其他编码数据就会产生乱码
解决方案:
前台后台都用UTF-8编码
客户端、服务器端全部采用UTF-8编码,且url发送中文字采用escape编码,unescape解码。
而且效率高,而且符合目前的形式,UTF-8编码本身就是一种比较优秀的编码。
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。
JSON建构有两种结构:
1. 键值对: { "name": "Alice", "sex":"female", "age": "18" }
2. 数组:
{ "people": [
{ "name": "Alice", "sex":"female", "age": "18" },
{ "name": "Scott", "sex":"male", "age": "35" }
]}
JSON 是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。
使用JSON可以很方便的和后台的Java对象进行数据传递,这也是Ajax中JSON大量使用的一个原因。
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。
它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样。
Jquery是继prototype之后又一个优秀的Javascrīpt框架。它是轻量级的js库(压缩后只有21k) ,它兼容CSS3,还兼容各种浏览器 (IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+)。jQuery使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互。jQuery还有一个比较大的优势是,它的文档说明很全,而且各种应用也说得很详细,同时还有许多成熟的插件可供选择。
JavaWeb部分的面试题,可能覆盖Servlet、JSP、EL表达式、JSTM标签库等相关内容,这些知识基本都可通过《轻量级JavaEE企业应用实战(第三版)整合开发》一书找到详细解答。这部分面试题大部分从网络收集、整理,也有部分题目来自疯狂软件学员面试之后的反馈。
1. get从地址栏以明文的方式提交请求信息内容?username=admin&password=123,用户可见, 而post从请求正文提交请求信息内容,用户不可见。
2. get提交因为是从地址栏传递,而浏览器的地址栏长度有限制,不能提交大数据
post从请求正文传递信息内容,对文件大小无限制,文件上传只能选择post
3. request对象是服务器获取请求信息(从请求头,请求正文中获取),我们可以使用request.setCharacterEncoding方法修改请求对象字符编码信息,但是不能修改地址栏字符编码。
get从地址栏传递信息,不能使用request.setCharacterEncoding这个方法去修改字符编码。post从请求正文以form表单形式提交,所以可以使用request.setCharacterEncoding这个方法去修改字符编码。
4. 总结: 能够使用post提交尽量使用post提交。
Servlet是sun公司提供的一门用于开发动态web资源的技术,是Java语言中编写Web服务器扩展功能的重要技术,同时它也是JSP技术的底层运行基础。
Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类.Servlet被编译为平台中立的字节码,可以被动态的加载到支持Java技术的Web服务器中运行。
Servlet是一个基于java技术的Web组件,运行在服务器端,由servlet容器管理,用于生成动态内容。
servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
Servlet被服务器实例化后,容器运行其init方法,该方法在整个生命周期中只运行一次,用于做一些准备工作,当该方法结束时该Servlet可以处理客户端请求。
请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,该方法在整个生命周期中运行多次,每个请求都使用service方法进行处理。
当服务器决定将实例销毁的时候调用其destroy方法,该方法在整个生命周期中只运行一次
,用于做一些清除工作。
1. forward服务器内部跳转(在当前webapp中跳转),地址栏不显示跳转后的url,
sendRedirect是地址栏重新发请求,地址栏显示的是跳转后的url
2. forward跳转时可以通过request共享数据,而sendRedirect不能通过request共享数据。
3. forward时前面是什么请求跳转就是什么请求,而sendRedirect一定是get请求。
4. 如果希望访问其他webapp的请求。
因为forward是服务器内部跳转,只在当前webapp跳转,所以是完成不了的。
sendRedirect("http://localhost:8080/userapp/register.html")
sendRedirect("/userapp/register.html")
sendRedirect相当于直接在地址栏输入请求,所以可以成功跳转。
一个Servlet对应有一个ServletConfig对象,可以用来读取初始化参数。
一个webapp对应一个ServletContext对象。
ServletContext对象获取初始化定义的参数。
ServletContext对象可以通过context.getResourceAsStream("/images/tomcat.gif");或者context.getRealPath("/")。
去获取webapp的资源文件。
ServletContext对象的setAttribute(String name,Object o)方法可以将对象存储在Context作用范围域又称为全局作用范围域,在整个web应用当中可以共享.
ServletContext对象可以和服务器进行通讯,比如写信息到服务器的日志信息当中。。
因为http协议是无状态协议,又称为一次性连接,所以webapp必须有一种机制
能够记住用户的一系列操作,并且唯一标示一个用户。
Cookie: 又称为小饼干,实际就是使用一个短文本保存用户信息,
在页面加载完毕是通过响应写回客户端进行保存。
Session: 在服务器保存数据,Session就是单个客户的一块内存, 用以存储数据。
Tomcat的Session是HashMap的实现。
当request.getSession()时Session对象被服务器创建,并且产生一个唯一的SessionID。
SessionID会通过Cookie写回客户端进行保存。如果Cookie被客户端禁用,只能使用URL重写机制。
Session对象可以使用setAttribute(String name,Object o)将对象存储在Session作用范围域中。Session作用范围域是在浏览器打开到浏览器关闭。
Filter是过滤器,在请求到达Servlet之前或者响应到达客户端之前截获请求或者响应,对之进行相应的处理。Struts2的控制器就是使用一个Filter实现的。
Listener是指Servlet中的监听器。
Listener可以对ServletContext对象、HttpSession对象、ServletRequest对象进行监听。
Servlet3.0相对于Servlet2.0来说最大的改变是引入了Annotation标注来取代xml配置,用于简化web应用的开发和部署。最主要几项特性:
1. 新增的注解支持:该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。
2. 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高 并发处理速度。
3. 可插性支持:熟悉 Struts2 的开发者一定会对其通过插件的方式与包括 Spring 在内的各种常用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。现在 Servlet 3.0 提供了类似的特性,开发者可以通过插件的方式很方便的扩充已有 Web 应用的功能,而不需要修改原有的应用。
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。在Servlet当中开发嵌入html的脚本,会非常的繁琐。JSP支持在html中直接嵌入java脚本,JSP是Servlet的简化设计,通常在开发中用来做展示数据。在实际开发中,Servlet负责响应请求并处理请求产生数据,数据的显示由JSP负责。
<% @ page %> <% @ include %> <% @ taglib %>
动态INCLUDE用jsp:include动作实现
<jsp:include page=included.jsp />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数.
静态INCLUDE用<%@ include file=included.htm %>指令实现,不会检查所含文件的变化,适用于包含静态页面.
外JSP共有以下7种基本动作
jsp:include:在页面被请求的时候引入一个文件。
jsp:useBean:寻找或者实例化一个JavaBean。
jsp:setProperty:设置JavaBean的属性。
jsp:getProperty:输出某个JavaBean的属性。
jsp:forward:把请求转到一个新的页面。
Jsp:param: 传递参数。
jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记
JSP共有以下9个内置的对象:
request请求对象
response 响应对象
pageContext 页面上下文对象
session 会话对象
application web应用上下文对象
out 输出对象
config 配置信息对象
page JSP网页本身
exception 针对错误网页,未捕捉的例外
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实例
JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。
Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。
而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
在实际项目开发当中,JSP侧重于视图,Servlet主要用于控制逻辑。
从关系数据库的表中删除冗余信息的过程称为数据规范化,是得到高效的关系型数据库表的逻辑结构最好和最容易的方法。
规范化数据时应执行以下操作:
1.将数据库的结构精简为最简单的形式
2.从表中删除冗余值
3.标识所有依赖与其他数据的数据
规范化过程有几个阶段,分别称作第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、第四范式(4NF)以及第五范式(5NF)。对于所有的实际应用,3NF已经足够了。
第一范式(1NF):字段具有原子性,不可再分。所有关系型数据库系统都满足第一范式)
数据库表中的字段都是单一属性的,不可再分。例如,姓名字段,其中的姓和名必须作为一个整体,无法区分哪部分是姓,哪部分是名,如果要区分出姓和名,必须设计成两个独立的字段。
第二范式(2NF):
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
要求数据库表中的每个实例或行必须可以被惟一地区分。通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。
第三范式(3NF)是在第二范式的基础上建立起来的,即满足第三范式(3NF)必须先满足第二范式(2NF)。
第三范式(3NF)要求非主关键字不能依赖于其他非主关键字。即非主关键字之间不能有函数(传递)依赖关系.即不能从一个表的某个字段推出该表的另一个字段。
满足三范式的设计,基本可以解决数据冗余、插入异常、更新异常、删除异常等数据存储问题。
SQL语句主要可以划分为以下几类:
DDL(Data Definition Language):数据定义语言,定义对数据库对象(库、表、列、索引)的操作。
包括:CREATE、DROP、ALTER、RENAME、 TRUNCATE等
DML(Data Manipulation Language): 数据操作语言,定义对数据库记录的操作。
包括:INSERT、DELETE、UPDATE、SELECT等
DCL(Data Control Language): 数据控制语言,定义对数据库、表、字段、用户的访问权限和安全级别。
包括:GRANT、REVOKE等
Transaction Control:事务控制
包括:COMMIT、ROLLBACK、SAVEPOINT等
delete 属于DML语句,删除数据,保留表结构,需要commit,可以回滚,如果数据量大,很慢。
truncate 属于DDL语句,删除所有数据,保留表结构,自动commit,不可以回滚,一次全部删除所有数据,速度相对较快。
Drop属于 DDL语句,删除数据和表结构,不需要commit,删除速度最快。
WHERE是在数据分组前进行条件过滤, HAVING子句是在数据分组后进行条件过滤,WHERE子句中不能使用聚合函数,HAVING子句可以使用聚合函数。
1.首先检查表的结构是否合理,因为采用多表查询的时候,看主外键的引用关系是否适当.如果不适当则重新设置表结构.如果是应用中的系统,则不需要更改表的字段,只更改主外键关系.如果数据库中有较多的数据,还应采用索引提高查询效率.
2.利用索引(index)对查询进行优化,index可以避免对表数据的全面扫描,当你以某个字段建立一个索引的时候,数据库就会生成一个索引页,索引页不单单保存索引的数据,还保存了索引在数据库的具体的物理地址,能够很快的定位查找到要找的记录
3. 如果表的列很少,不适合建索引.表数据很少查询,而经常做insert、delete、update动作,不适合建所以。因为Oracle需要对索引额外维护。建立索引后,select会快, 当执行过多次的insert,delete,update后,会出现索引碎片,影响查询速度,我们应该对索引进行重组(即drop掉索引重新create)
4.索引的类型分为:
B-树索引:适合于大量的增、删、改,大多数数据的索引默认类型。
位图索引:适合于决策支持系统
HASH索引、分区索引等。
事务是作为一个逻辑单元执行的一系列操作,要么一起成功,要么一起失败。
一个逻辑工作单元必须有四个属性,称为 ACID(原子性、致性、隔离性和持久性)属性,只有这样才能成为一个事务。
原子性 :事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性 :事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。
隔离性 :由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执的状态相同。
持久性 :事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。
数据库共定义了四种隔离级别:
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)
Read committed:可避免脏读情况发生(读已提交)。
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
1.通过创建临时表
creat table tbl_tmp as select distinct * from tbl;
truncate table tbl;//清空表记录
insert into tbl select * from tbl_tmp;//将临时表中的数据插回来。
2.利用rowid
delete from tbl where rowid in
(select a.rowid from tbl a, tbl b
where a.rowid>b.rowid
and a.col1=b.col1 and a.col2 = b.col2)
3.利用max或min函数
delete from tbl a where rowid not in
(select max(b.rowid) from tbl b where a.col1=b.col1 and a.col2 = b.col2);
//这里max使用min也可以
delete from tbl where rowid not in
(select max(rowid) from tbl tgroup by t.col1, t.col2);
oracle
select rownum,bookId from
[rownum是伪列名,bookId是列名]
(select rownum row_id,bookId from xiaoWJ_books t)
t where row_id between 10 and 20
[查10到20条记录]
mysql
sql="select * from xiaoWJ_books LIMIT ?,?";
第一个?是开始位置,第二个?是每页显示多少
sqlServer2000
select top "+pageSize+" * from xiaoWJ_books where bookId not in
[去掉前面 "+pageBegin+" 条后显示 "+pageSize+" 条记录]
(select top "+pageBegin+" bookId from xiaoWJ_books order by bookId)
[查出整个表的前 "pageBegin" 条记录]
order by bookId"
Oracle的备份与恢复有三种标准的模式,大致分为两大类,备份恢复(物理上的)以及导入导出(逻辑上的),而备份恢复又可以根据数据库的工作模式分为非归档模式(Nonarchivelog-style)和归档模式(Archivelog-style),通常,我们把非归档模式称为冷备份,而相应的把归档模式称为热备份。
逻辑备份方式的方法,利用Export可将数据从数据库中提取出来,利用Import则可将提取出来的数据送回到Oracle数据库中去。如:
导出数据文件: exp scott/tiger file=d:/scott.dmp
导入数据文件: imp scott/tiger file=:/scott.dmp
以Oracle数据库举例:
(a-G要求掌握,H一般为DBA操作,了解就可以了)
a。
建库:已知将保存海量数据的时候,因为Oracle是通过用户来管理数据的,
第一步我们先建一个tableaspace(假设表空间名为TEST),
然后建立用户TEST(一般情况下用户名和表空间同名),
建立的用户TEST使用已建立的tablespace(TEST).
这样做是避免访问上产生热点。
b。
建表:建表时最好依照第三范式去建表(请回答三个范式),
这样可以最大程度避免出现数据冗余、插入、删除和更新异常,保证数据完整性。
而且表结构合理的情况下,可以加快查询速度。
c。
索引:在经常查询的字段上面建立索引,
利用index对查询进行优化,(index可以避免对表的一个全面扫描)
原理:当以某个字段建立一个索引的时候,数据库就会生成一个索引页,
索引页不单单保存索引的数据,还保存了索引在数据库的具体的物理地址,
当我们查询数据时,oracle会先查索引页,这样就能够很快的定位查找到要找的记录)。
注意:
如果表的列很少,不适合建索引.
当执行过多次的insert,delete,update后,会出现索引碎片,
影响查询速度,我们应该对索引进行重组.
D:
sql语句的优化:
多使用共享语句
尽量使你的sql语句能够使用索引。
怎样使sql语句能够使用到索引呢:
当sql语句中包含not in,<>,is null,is not null,like '%%'的时候不会用索引。
IN: in会拆成一堆or的,可以使用表的索引。
NOT IN:强列推荐不使用,因为它不能应用表的索引。
<> 操作符(不等于): 不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
优化方案:用其它相同功能的操作运算代替,如a<>0 改为 a>0 or a<0;a<>’’ 改为 a>’’.
IS NULL 或IS NOT NULL操作(判断字段是否为空):
判断字段是否为空一般是不会应用索引的,因为B树索引(oracle大多是使用B树索引)是不索引空值的。
优化方案:用其它相同功能的操作运算代替,如 a is not null 改为 a>0 或a>’’等。
is null 时,用一个缺省值代替空值,例如业扩申请中状态字段不允许为空,缺省为申请。
LIKE:LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,
优化方案:如LIKE ‘%001%’ 这种查询不会引用索引,会产生全表扫描,
而LIKE ‘001%’则会引用范围索引。进行范围的查询,性能肯定大大提高。
E:
多表查询时,一般一个大表关联几个小表,最好不要几个大表相关联,那样也会影响到查询速度。
F:
oralce访问表中的数据共有三种方式,全表扫描,通过索引扫描,使用共享语句(一模一样)。
select id,name from tb_sutdent;
Select id,name from tb_sutdent;
我们JDBC查询中使用PreparedStatement实际上就是使用共享语句。
所以我们要多使用共享语句来加快查询速度。
G:
经常查询的SQL可以写成存储过程。
H:
当表数据达到几十到几百GB时,就要考虑对表进行分区了,
分区的优点:
1.增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用
2.维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
3.均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
4.改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
分区的几种方法:范围分区 ,Hash分区(散列分区) ,复合分区 。
应用:实际项目中大多使用范围分区,
例如按时间范围(日期字段)来分区,如2005-2006数据作为一个分区,2006-2007作为一个分区。
JDBC部分的面试题,可能覆盖数据库和JDBC等相关内容,这些知识基本都可通过《轻量级JavaEE企业应用实战(第三版)整合开发》一书找到详细解答。这部分面试题大部分从网络收集、整理,也有部分题目来自疯狂软件学员面试之后的反馈。
1. 注册数据库驱动。
2. 建立数据库连接。
3. 创建一个Statement。
4. 执行SQL语句。
5. 处理结果集。
6. 关闭数据库连接。
PreparedStatement是预编译的SQL语句,效率高于Statement。
PreparedStatement支持?操作符,相对于Statement更加灵活。
PreparedStatement可以防止SQL注入,安全性高于Statement。
最好的办法是利用sql语句进行分页,这样每次查询出的结果集中就只包含某页的数据内容。
sql语句分页,不同的数据库下的分页方案各不一样,下面是主流的三种数据库的分页sql:
oracle:
select * from
(select *,rownum as tempid from student ) t
where t.tempid between " + pageSize*(pageNumber-1) + " and " + pageSize*pageNumber
mysql:
select * from students limit " + pageSize*(pageNumber-1) + "," + pageSize;
sql server:
select top " + pageSize + " * from students where id not in +
(select top " + pageSize * (pageNumber-1) + id from students order by id) +
"order by id;
工作原理:JAVA EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。
实现方案:返回的Connection是原始Connection的代理,代理Connection的close方法,当调用close方法时,不是真正关连接,而是把它代理的Connection对象放回到连接池中,等待下一次重复利用。
流行框架部分的面试题,可能覆盖Struts、Hibernate、Spring等相关内容,这些知识基本都可通过《轻量级JavaEE企业应用实战(第三版)整合开发》一书找到详细解答。这部分面试题大部分从网络收集、整理,也有部分题目来自疯狂软件学员面试之后的反馈。
MVC (Model View Controller) 是一个设计模式,使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以应用于不同的表现形式。
MODEL: 封装了所有的商业逻辑以及规则。通常被JavaBean或EJB实现。
VIEW: 使用商业逻辑处理后的结果并构建呈现给客户端的响应。通常被JSP实现。 CONTROLLER:管理和控制所有用户和应用程序间的交互。通常是一个servlet接收用户的请求并把所有的输入转交给实际工作的MODEL。最后调用JSP返回输出。
MVC模式的好处:
1.各施其职,互不干涉
在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。
2.有利于开发中的分工
在MVC模式中,由于按层把系统开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。
3.有利于组件的重用
分层后更有利于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。
Struts就是一个基于MVC模式的框架。
特性 | Struts1 | Struts2 |
Action | Struts1.x要求Action类要扩展自一个抽象基类。Struts1.x的一个共有的问题是面向抽象类编程而不是面向接口编程。 | Struts2的Action类实现了一个Action接口,连同其他接口一起来实现可选择 和自定义的服务。Struts2提供一个名叫ActionSupport的基类来实现一般使用的接口。当然,Action接口不是必须的。任何使用 execute方法的POJO对象可以被当作Struts 2的Action对象来使用。 |
线程模型 | Struts1.x Action类是单例类,因为只有一个实例来控制所有的请求。单例类策略造成了一定的限制,并且给开发带来了额外的烦恼。Action资源必须是线程安全 或者同步的。 | Struts2 Action对象为每一个请求都实例化对象,所以没有线程安全的问题。(实践中,servlet容器给每一个请求产生许多丟弃的对象,并且不会导致性能和 垃圾回收问 |
Servlet依赖 | Struts1.x的Action类依赖于servlet API,当Action被调用时,以HttpServletRequest和HttpServletResponse作为参数传给execute方法。 | Struts2的Action和容器无关。Servlet上下文被表现为简单的Maps,允 许Action被独立的测试。Struts2的Action可以访问最初的请求(如果需要的话)。但是,尽可能避免或排除其他元素直接访问 HttpServletRequest或HttpServletResponse。 |
易测性 | 测试Struts1.x的主要问题是execute方法暴露了Servlet API这使得测试要依赖于容器)。第三方的扩展,如Struts TestCase,提供了一套Struts1的模拟对象(来进行测试)。 | Struts2的Action可以通过初始化、设置属性、调用方法来测试。依赖注入的支持也是测试变得更简单。 |
捕获输入 | Struts1.x使用ActionForm对象来捕获输入。象Action一样,所有的 ActionForm必须扩展基类。因为其他的JavaBean不能作为ActionForm使用,开发者经常创建多余的类来捕获输入。 DynaBeans可以被用来作为替代ActionForm的类来创建。但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有 冗余的javabean)。 | Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入 属性可能是有自己(子)属性的rich对象类型。Action属性能够通过web页面上的taglibs访问。Struts2也支持ActionForm 模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种ModelDriven 特性简化了taglib对POJO输入对象的引用。 |
表达式语言 | Struts1.x整合JSTL,所以它使用JSTL的表达式语言。表达式语言有基本的图形对象移动,但是对集合和索引属性的支持很弱。 | Struts2使用JSTL,但是也支持一个更强大和灵活的表达式语言--”Object Graph Notation Language” (OGNL)。 |
将值绑定到页面 | Struts1.x使用标准JSP机制来绑定对象到页面上下文。 | Struts2使用“ValueStack”技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允 许通过一系列名称相同但类型不同的属性重用页面(view) |
类型转换 | Struts1.x的ActionForm属性经常都是String。Struts 1.x使用Commons-Beanutils来进行类型转换。转换每一个类,而不是为每一个实例配置。 | Struts2使用OGNL进行类型转换。提供基本和常用对象的转换器。 |
验证 | Struts1.x支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。 | Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持 chain校验子属性 |
Action执行控制 | Struts1.x支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。 | Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。 |
4. Struts2的功能扩展点有哪些?
l Interceptor及其相关子类
l TypeConverter及其相关子类
l Validator及其相关子类
l Result及其相关子类
l ObjectFactory及其相关子类
值栈 Value Stack
值栈是Struts2框架的核心概念。所有的核心组件都以某种方式与之进行交互,它提供对上下文信息和执行环境中元素的访问机制。值栈的内容由如下4个层级组成。
1.临时对象
这些对象在请求处理中需要临时保存,比如集合中当前正在被迭代的元素。
2.模型对象
当action实现了ModelDriven接口,模型对象就会被存放在栈中,在action对象前。如果action没有实现该接口,这个级别的内容将不存在。
3.Action对象
此对象是当前正在执行的action。
4.命名对象 即 OGNL上下文环境
任何对象都可以被赋予一个标识符而成为命名对象。Struts2内建的命名对象有:#application、#session、#request、#attr、#parameters
使用值栈不需要压栈和弹栈,可直接使用OGNL表达式来查找或求值。OGNL表达式会在每个层级测试,层级测试的顺序按照层级顺序进行。如果各层级都没有求出结果,那么则返回null值。
Struts 2.1 的隐式对象
(这些隐式对象都是Map类型)
parameters 用于访问请求参数
request 用于访问HttpServletRequest的属性
session 用于访问HttpSession的属性
application 用于访问ServletContext的属性
attr 用于访问各作用域内的属性,将依次搜索 request > session > application
1. 通过ActionContext.getSession获取
2. 通过ServletActionContext.getRequest()获取
3. 通过SessionAware接口注入
4. 通过ServletRequestAware接口注入
Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
拦截器栈(Interceptor Stack)类似于过滤器链。拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器栈的拦截器就会按其之前定义的顺序被调用。
Struts2的拦截器和Filter类似。在执行Action的execute方法之前,Struts2会首先执行在struts.xml中引用的拦截器,完成一系列的功能,在执行完所有引用的拦截器的intercept方法后,会执行Action的execute方法。
ORM的全称是Object-Relational Mapping,即对象关系映射。ORM思想的提出来源于对象与关系之间相悖的特性。我们很难通过对象的继承与聚合关系来描述数据表中一对一、一对多以及多对多的关系。而面向对象思想中有关抽象与多态的原理,也无法通过关系数据库的SQL语句得以彰显。因此,我们需要在面向对象与面向关系之间找到一个平衡点,ORM于是应运而生。
目前ORM框架的产品非常之多,除了个大公司、组织的产品外,其他一些小团队也在推出自己的ORM框架。目前流行的ORM框架有如下这些产品:
(1)Enitiy EJB:Enitiy EJB实际上也是一种ORM技术,这是一直备受争议的组件技术。事实上,EJB为Java EE的蓬勃发展赢得了极高的声誉,EJB作为一种重量级、高花费的ORM技术具有不可比拟的优势。就其他架构设计来讲,依然非常优秀。即使现在十分流行的轻量级Java EE架构,其实质是对经典Java EE架构的模仿——虽然存在些许的改进。EJB3.1也采取了低侵入式的设计,增加了Annotation,也具有极大的吸引力。
(2)Hibernate:目前最流行的开源ORM框架,已经被选作JBoss的持久层解决方案。整个HIbernate项目也一并投入了Jboss的怀抱,而JBoss又加入了RedHat组织,所以现在Hibernate属于RedHat 的一部分。Hibernate 灵巧的设计、优秀的性能,还有其丰富的文档都是其风靡全球的重要因素。
(3)iBatis: Apache软件基金组织的子项目。与其称它为一种ORM框架,不如称它为一中“SQL Mapping”框架。曾经在J2EE的开发中扮演非常重要的角色,但因为不支持存粹的面向对象操作,因此现在逐渐地被取代。但是在一些公司,依然占有一席之地,特别是一些对数据访问特别灵活的地方,iBatis更加的灵活,它允许开发人员直接编写SQL语句。
(4)TopLink:Oracle公司的产品,作为一个遵循OTN协议的商业产品,TopLink 在开发过程中可以自由地下载和使用,但是一旦作为商业产品被使用,则需要收取费用。由于这一点,TopLink 的市场占有率不高。
(5)OBJ:Apache软件基金组织的子项目。另一个开源的ORM框架,可以说是Apache作为iBatis之后的取代产品,也是非常优秀的O/R Mapping框架,但是由于Hibernate 的广芒太盛,所以并未有广泛的使用,而且由于OJB的开发文档不是很多,这也影响了OJB的流行。
Hibernate是一个轻量级的持久层开源框架,它是连接Java应用程序和关系数据库的中间件,负责Java对象和关系数据之间的映射.Hibernate内部对JDBC API进行了封装,负责Java对象的持久化.因为它封装了所有的数据访问细节,使得业务逻辑层可以专注于实现业务逻辑.
它是一种优秀的ORM映射工具,提供了完善的对象-关系映射服务,开发过程不依赖容器,灵活性非常大,可以无缝集成到任何一个java系统中.
JDBC和Hibernate都是用于数据持久化操作的。
JDBC:
1.实现业务逻辑的代码和访问数据库的代码混杂在一起,使程序结构不清晰,可读性差.
2.Java是面向对象的,sql是面向关系的.两者混在一起,程序员不能完全的运用面向对象的思维来编写程序.
3.业务逻辑和关系数据模型绑定,如果关系数据模型发生变化(如更改表结构),就必须手动修改程序里所有相关的sql语句,增加了维护软件的难度.如果sql语句有语法错误,编译是不能检查这种错误,只有运行时才能发现错误,增加了程序的调试难度.
4.数据库移植困难。
Hibernate:
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和 Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。下面对这五的核心接口分别加以介绍。
Session接口:Session接口负责执行被持久化对象的CRUD操作。但需要注意的是Session对象是非线程安全的。
SessionFactory接口:SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建 Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个 SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
Configuration接口:Configuration接口负责配置并启动Hibernate,创建SessionFactory对象。在 Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。
Transaction接口:Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。
Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。
其区别在于:
Get会发送查询语句提取数据,而load方法当对象使用时才去数据库查询。
如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException。
Load方法可返回实体的代理类实例,而get方法永远直接返回实体类。
load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。
瞬时态(Transient)、 持久态(Persistent)、脱管态(Detached)。处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object)。
瞬时态:
没有持久化标示符,数据库中无对应记录。当执行save和persist方法可以变成持久态。
持久态
处于该状态的对象在数据库中具有对应的记录,并拥有一个持久化标识。如果是用hibernate的delete()方法,对应的持久对象就变成瞬时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联。当一个session执行close()或clear()、evict()之后,持久对象变成脱管对象,此时持久对象会变成脱管对象,此时该对象虽然具有数据库识别值,但它已不在HIbernate持久层的管理之下。
持久对象具有如下特点:
1. 和session实例关联;
2. 在数据库中有与之关联的记录。
脱管态
当与某持久对象关联的session被关闭后,该持久对象转变为脱管对象。当脱管对象被重新关联到session上时,并再次转变成持久对象。
脱管对象拥有数据库的识别值,可通过update()、saveOrUpdate()等方法,转变成持久对象。
脱管对象具有如下特点:
1. 本质上与瞬时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它回收;
2. 比瞬时对象多了一个数据库记录标识值。
大体上,对于HIBERNATE性能调优的主要考虑点如下:
l 数据库设计调整
l HQL优化
l API的正确使用(如根据不同的业务类型选用不同的集合及查询API)
l 主配置参数(日志,查询缓存,fetch_size, batch_size等)
l 映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)
l 一级缓存的管理
l 针对二级缓存,还有许多特有的策略
l 事务控制策略。
(下面是说明不需要回答)
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的选择等)才是最重要的。
HQL功能很强大,适合各种情况,但是动态条件查询构造起来很不方便;
Criteria 最适合动态查询,但不太适合统计查询,QBE还不够强大.只适合简单的查询;
Native-SQL可以实现特定的数据库的SQL,但是可移植性并不好。
如大部分查询都是动态条件查询,首先criteria,甚至使用Hibernate3提供的DetachedCriteria,构造好DetachedCriteria再进入Session执行查询。
但是涉及到统计查询和非常复杂的关联查询,Criteria就无能为力了。这种情况下选择使用HQL。最后如果涉及到使用某些数据库的特性的时候,就只有选择Native-SQL了
第一级缓存由Session实例维护,它是必选的,其中保持了Session当前所有关联实体的数据,也称为内部缓存。而第二级缓存则存在于SessionFactory层次,它是可选的。一级缓存只能为当前线程的会话缓存,无法给整个应用共享;二级缓存可为整个应用提供缓存支持。二级缓存可以开启查询缓存,而一级缓存不行。
Spring是一个轻量级的容器,非侵入性的框架.最重要的核心概念是IOC,并提供AOP概念的实现方式,提供对持久层,事务的支持,对当前流行的一些框架(Struts,Hibernate,MVC),Sping也提供了与它们的相整合的方案.使用Spring,我们能够减少类之间的依赖性和程序之间的耦合度,最大程度的实现松耦合,使程序更加灵活,可扩展性更强.使用Spring,使得开发人员可以真正的专注于业务逻辑,而不是代码。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP是目前软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP是OOP的延续,主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
在Spring中提供了AOP的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
Required
如果当前存在一个事务,则加入当前事务。如果不存在任何事务,则创建一个新的事务。总之,要至少保证在一个事务中运行。PROPAGATION_REQUIRED通常作为默认的事务传播行为。
RequiresNew
不管当前是否存在事务,都会创建新的事务。如果当前存在事务,会将当前的事务挂起(Suspend)。如果某个业务对象所做的事情不想影响到外层事务,PROPAGATION_REQUIRES_NEW应该是合适的选择。
标签:基于 代理类 应对 mic 持久化 网络 搜索 apache 变更
原文地址:http://blog.51cto.com/10913595/2071349