`
gcgmh
  • 浏览: 358522 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java编程经验汇总2(转载)

阅读更多
笔者之前说的都是Struts-1,因为新出了Struts-2,使得每次谈到Struts都必须注明它是Struts-1还是2。笔者先谈比较熟悉的 Struts-1,下次再介绍一下与Struts-2的区别:

1. Struts框架整体结构
Struts-1的核心功能是前端控制器,程序员需要关注的是后端控制器。前端控制器是是一个Servlet,在Web.xml中间配置所有 Request都必须经过前端控制器,它的名字是ActionServlet,由框架来实现和管理。所有的视图和业务逻辑隔离都是应为这个 ActionServlet, 它就像一个交通警察,所有过往的车辆必须经过它的法眼,然后被送往特定的通道。所有,对它的理解就是分发器,我们也可以叫做Dispatcher,其实了解Servlet编程的人自己也可以写一个分发器,加上拦截request的Filter,其实自己实现一个struts框架并不是很困难。主要目的就是让编写视图的和后台逻辑的可以脱离紧耦合,各自同步的完成自己的工作。

那么有了ActionServlet在中间负责转发,前端的视图比如说是Jsp,只需要把所有的数据Submit,这些数据就会到达适合处理它的后端控制器Action,然后在里面进行处理,处理完毕之后转发到前台的同一个或者不同的视图Jsp中间,返回前台利用的也是Servlet里面的forward 和redirect两种方式。所以到目前为止,一切都只是借用了Servlet的API搭建起了一个方便的框架而已。这也是Struts最显著的特性?? 控制器。

那么另外一个特性,可以说也是Struts-1带来的一个比较成功的理念,就是以xml配置代替硬编码配置信息。以往决定Jsp往哪个servlet提交,是要写进Jsp代码中的,也就是说一旦这个提交路径要改,我们必须改写代码再重新编译。而Struts提出来的思路是,编码的只是一个逻辑名字,它对应哪个class文件写进了xml配置文件中,这个配置文件记录着所有的映射关系,一旦需要改变路径,改变xml文件比改变代码要容易得多。这个理念可以说相当成功,以致于后来的框架都延续着这个思路,xml所起的作用也越来越大。

大致上来说Struts当初给我们带来的新鲜感就这么多了,其他的所有特性都是基于方便的控制转发和可扩展的xml配置的基础之上来完成它们的功能的。
下面将分别介绍Action和FormBean, 这两个是Struts中最核心的两个组件。

2. 后端控制器Action
Action就是我们说的后端控制器,它必须继承自一个Action父类,Struts设计了很多种Action,例如DispatchAction、 DynaValidationAction。它们都有一个处理业务逻辑的方法execute(),传入的request, response, formBean和actionMapping四个对象,返回actionForward对象。到达Action之前先会经过一个 RequestProcessor来初始化配置文件的映射关系,这里需要大家注意几点:

1) 为了确保线程安全,在一个应用的生命周期中,Struts框架只会为每个Action类创建一个Action实例,所有的客户请求共享同一个Action 实例,并且所有线程可以同时执行它的execute()方法。所以当你继承父类Action,并添加了private成员变量的时候,请记住这个变量可以被多个线程访问,它的同步必须由程序员负责。(所有我们不推荐这样做)。在使用Action的时候,保证线程安全的重要原则是在Action类中仅仅使用局部变量,谨慎的使用实例变量。局部变量是对每个线程来说私有的,execute方法结束就被销毁,而实例变量相当于被所有线程共享。

2) 当ActionServlet实例接收到Http请求后,在doGet()或者doPost()方法中都会调用process()方法来处理请求。 RequestProcessor类包含一个HashMap,作为存放所有Action实例的缓存,每个Action实例在缓存中存放的属性key为 Action类名。在RequestProcessor类的processActionCreate()方法中,首先检查在HashMap中是否存在 Action实例。创建Action实例的代码位于同步代码块中,以保证只有一个线程创建Action实例。一旦线程创建了Action实例并把它存放到 HashMap中,以后所有的线程会直接使用这个缓存中的实例。

3) <action> 元素的 <roles> 属性指定访问这个Action用户必须具备的安全角色,多个角色之间逗号隔开。RequestProcessor类在预处理请求时会调用自身的 processRoles()方法,检查配置文件中是否为Action配置了安全角色,如果有,就调用HttpServletRequest的 isUserInRole()方法来判断用户是否具备了必要的安全性角色,如果不具备,就直接向客户端返回错误。(返回的视图通过 <input> 属性来指定)

3. 数据传输对象FormBean
Struts并没有把模型层的业务对象直接传递到视图层,而是采用DTO(Data Transfer Object)来传输数据,这样可以减少传输数据的冗余,提高传输效率;还有助于实现各层之间的独立,使每个层分工明确。Struts的DTO就是 ActionForm,即formBean。由于模型层应该和Web应用层保持独立。由于ActionForm类中使用了Servlet API, 因此不提倡把ActionForm传递给模型层, 而应该在控制层把ActionForm Bean的数据重新组装到自定义的DTO中, 再把它传递给模型层。它只有两个scope,分别是session和request。(默认是session)一个ActionForm标准的生命周期是:
1) 控制器收到请求 ->
2) 从request或session中取出ActionForm实例,如不存在就创建一个 ->
3) 调用ActionForm的reset()方法 ->
4) 把实例放入session或者request中 ->
5) 将用户输入表达数据组装到ActionForm中 ->
6) 如眼张方法配置了就调用validate()方法 ->
7) 如验证错误就转发给 <input> 属性指定的地方,否则调用execute()方法

validate()方法调用必须满足两个条件:
1) ActionForm 配置了Action映射而且name属性匹配
2) <aciton> 元素的validate属性为true

如果ActionForm在request范围内,那么对于每个新的请求都会创建新的ActionForm实例,属性被初始化为默认值,那么reset ()方法就显得没有必要;但如果ActionForm在session范围内,同一个ActionForm实例会被多个请求共享,reset()方法在这种情况下极为有用。

4. 验证框架和国际化
Struts有许多自己的特性,但是基本上大家还是不太常用,说白了它们也是基于JDK中间的很多Java基础包来完成工作。例如国际化、验证框架、插件自扩展功能、与其他框架的集成、因为各大框架基本都有提供这样的特性,Struts也并不是做得最好的一个,这里也不想多说。Struts的验证框架,是通过一个validator.xml的配置文件读入验证规则,然后在validation-rules.xml里面找到验证实现通过自动为Jsp插入 Javascript来实现,可以说做得相当简陋。弹出来的JavaScript框不但难看还很多冗余信息,笔者宁愿用formBean验证或者 Action的saveErrors(),验证逻辑虽然要自己写,但页面隐藏/浮现的警告提示更加人性化和美观一些。

至于Struts的国际化,其实无论哪个框架的国际化,java.util.Locale类是最重要的Java I18N类。在Java语言中,几乎所有的对国际化和本地化的支持都依赖于这个类。如果Java类库中的某个类在运行的时候需要根据Locale对象来调整其功能,那么就称这个类是本地敏感的(Locale-Sensitive), 例如java.text.DateFormat类就是,依赖于特定Locale。

创建Locale对象的时候,需要明确的指定其语言和国家的代码,语言代码遵从的是ISO-639规范,国家代码遵从ISO-3166规范,可以从
http://www.unicode.org/unicode/onlinedat/languages.html
http://www.unicode.org/unicode/onlinedat/countries.htm

Struts的国际化是基于properties的message/key对应来实现的,笔者曾写过一个程序,所有Jsp页面上没有任何Text文本串,全部都用的是 <bean:message> 去Properties文件里面读,这个时候其实只要指定不同的语言区域读不同的Properties文件就实现了国际化。需要注意的是不同语言的字符写进Properties文件的时候需要转化成Unicode码,JDK已经带有转换的功能。JDK的bin目录中有native2ascii这个命令,可以完成对*.txt和*.properties的Unicode码转换。

OK,今天就说到这里,本文中的很多内容也不是笔者的手笔,是笔者一路学习过来自己抄下来的笔记,希望对大家有帮助!Java杂谈一路走来,感谢大家持续的关注,大概再有个2到3篇续篇就改完结了!笔者尽快整理完成后续的写作吧……^_^
Java杂谈(九)--Struts2
Java杂谈(九)--Struts2


最近业余时间笔者一直Java Virtual Machine的研究,由于实习分配到项目组里面,不想从前那么闲了,好不容易才抽出时间来继续这个话题的帖子。我打算把J2ee的部分结束之后,再谈谈 JVM和JavaScript,只要笔者有最新的学习笔记总结出来,一定会拿来及时和大家分享的。衷心希望与热爱Java的关大同仁共同进步……

这次准备继续上次的话题先讲讲Struts-2,手下简短回顾一段历史:随着时间的推移,Web应用框架经常变化的需求,产生了几个下一代 Struts的解决方案。其中的Struts Ti 继续坚持 MVC模式的基础上改进,继续Struts的成功经验。 WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想,概念和功能,但和原Struts代码并不兼 容。WebWork是一个成熟的框架,经过了好几次重大的改进与发布。在2005年12月,WebWork与Struts Ti决定合拼, 再此同时, Struts Ti 改名为 Struts Action Framework 2.0,成为Struts真正的下一代。

看看Struts-2的处理流程:
1) Browser产生一个请求并提交框架来处理:根据配置决定使用哪些拦截器、action类和结果等。
2) 请求经过一系列拦截器:根据请求的级别不同拦截器做不同的处理。这和Struts-1的RequestProcessor类很相似。
3) 调用Action: 产生一个新的action实例,调用业务逻辑方法。
4) 调用产生结果:匹配result class并调用产生实例。
5) 请求再次经过一系列拦截器返回:过程也可配置减少拦截器数量
6) 请求返回用户:从control返回servlet,生成Html。

这里很明显的一点是不存在FormBean的作用域封装,直接可以从Action中取得数据。 这里有一个Strut-2配置的web.xml文件:
<filter>
<filter-name> controller </filter-name>
<filter-class> org.apache.struts.action2.dispatcher.FilterDispatcher </filter-class>
</filter>
<filter-mapping>
<filter-name> cotroller </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

注意到以往的servlet变成了filter,ActionServlet变成了FilterDispatcher,*.do变成了/*。filter 配置定义了名称(供关联)和filter的类。filter mapping让URI匹配成功的的请求调用该filter。默认情况下,扩展名为 ".action "。这个是在default.properties文件里的 "struts.action.extension "属性定义的。

default.properties是属性定义文件,通过在项目classpath路径中包含一个名为“struts.properties”的文件来设置不同的属性值。而Struts-2的默认配置文件名为struts.xml。由于1和2的action扩展名分别为.do和.action,所以很方便能共存。我们再来看一个Struts-2的action代码:
public class MyAction {
public String execute() throws Exception {
//do the work
return "success ";
}
}

很明显的区别是不用再继承任何类和接口,返回的只是一个String,无参数。实际上在Struts-2中任何返回String的无参数方法都可以通过配置来调用action。所有的参数从哪里来获得呢?答案就是Inversion of Control技术(控制反转)。笔者尽量以最通俗的方式来解释,我们先试图让这个Action获得reuqest对象,这样可以提取页面提交的任何参数。那么我们把request设为一个成员变量,然后需要一个对它的set方法。由于大部分的action都需要这么做,我们把这个set方法作为接口来实现。
public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}

public class MyAction implements ServletRequestAware {
private HttpServletRequest request;

public void setServletRequest(HttpServletRequest request) {
this.request = request;
}

public String execute() throws Exception {
// do the work directly using the request
return Action.SUCCESS;
}
}

那么谁来调用这个set方法呢?也就是说谁来控制这个action的行为,以往我们都是自己在适当的地方写上一句 action.setServletRequest(…),也就是控制权在程序员这边。然而控制反转的思想是在哪里调用交给正在运行的容器来决定,只要利用Java反射机制来获得Method对象然后调用它的invoke方法传入参数就能做到,这样控制权就从程序员这边转移到了容器那边。程序员可以减轻很多繁琐的工作更多的关注业务逻辑。Request可以这样注入到action中,其他任何对象也都可以。为了保证action的成员变量线程安全, Struts-2的action不是单例的,每一个新的请求都会产生一个新的action实例。

那么有人会问,到底谁来做这个对象的注入工作呢?答案就是拦截器。拦截器又是什么东西?笔者再来尽量通俗的解释拦截器的概念。大家要理解拦截器的话,首先一定要理解GOF23种设计模式中的Proxy模式。

A对象要调用f(),它希望代理给B来做,那么B就要获得A对象的引用,然后在B的f()中通过A对象引用调用A对象的f()方法,最终达到A的f()被调用的目的。有没有人会觉得这样很麻烦,为什么明明只要A.f()就可以完成的一定要封装到B的f()方法中去?有哪些好处呢?

1) 这里我们只有一个A,当我们有很多个A的时候,只需要监视B一个对象的f()方法就可以从全局上控制所有被调用的f()方法。
2) 另外,既然代理人B能获得A对象的引用,那么B可以决定在真正调A对象的f()方法之前可以做哪些前置工作,调完返回前可有做哪些后置工作。

讲到这里,大家看出来一点拦截器的概念了么?它拦截下一调f()方法的请求,然后统一的做处理(处理每个的方式还可以不同,解析A对象就可以辨别),处理完毕再放行。这样像不像对流动的河水横切了一刀,对所有想通过的水分子进行搜身,然后再放行?这也就是AOP(Aspect of Programming面向切面编程)的思想。

Anyway,Struts-2只是利用了AOP和IoC技术来减轻action和框架的耦合关系,力图到最大程度重用action的目的。在这样的技术促动下,Struts-2的action成了一个简单被框架使用的POJO(Plain Old Java Object)罢了。实事上AOP和IoC的思想已经遍布新出来的每一个框架上,他们并不是多么新的技术,利用的也都是JDK早已可以最到的事情,它们代表的是更加面向接口编程,提高重用,增加扩展性的一种思想。Struts-2只是部分的使用这两种思想来设计完成的,另外一个最近很火的框架 Spring,更大程度上代表了这两种设计思想,笔者将于下一篇来进一步探讨Spring的结构。

PS: 关于Struts-2笔者也没真正怎么用过,这里是看了网上一些前辈的帖子之后写下自己的学习体验,不足之处请见谅!
Java杂谈(十)--Spring
Java杂谈(十)--Spring


笔者最近比较忙,一边在实习一边在寻找明年毕业更好的工作,不过论坛里的朋友非常支持小弟继续写,今天是周末,泡上一杯咖啡,继续与大家分享J2ee部分的学习经验。今天的主题是目前很流行也很好的一个开源框架-Spring。

引用《Spring2.0技术手册》上的一段话:
Spring的核心是个轻量级容器,它是实现IoC容器和非侵入性的框架,并提供AOP概念的实现方式;提供对持久层、事务的支持;提供MVC Web框架的实现,并对于一些常用的企业服务API提供一致的模型封装,是一个全方位的应用程序框架,除此之外,对于现存的各种框架,Spring也提供了与它们相整合的方案。
接下来笔者先谈谈自己的一些理解吧,Spring框架的发起者之前一本很著名的书名字大概是《J2ee Development without EJB》,他提倡用轻量级的组件代替重量级的EJB。笔者还没有看完那本著作,只阅读了部分章节。其中有一点分析觉得是很有道理的:

EJB里在服务器端有Web Container和EJB Container,从前的观点是各层之间应该在物理上隔离,Web Container处理视图功能、在EJB Container中处理业务逻辑功能、然后也是EBJ Container控制数据库持久化。这样的层次是很清晰,但是一个很严重的问题是Web Container和EJB Container毕竟是两个不同的容器,它们之间要通信就得用的是RMI机制和JNDI服务,同样都在服务端,却物理上隔离,而且每次业务请求都要远程调用,有没有必要呢?看来并非隔离都是好的。

再看看轻量级和重量级的区别,笔者看过很多种说法,觉得最有道理的是轻量级代表是POJO + IoC,重量级的代表是Container + Factory。(EJB2.0是典型的重量级组件的技术)我们尽量使用轻量级的Pojo很好理解,意义就在于兼容性和可适应性,移植不需要改变原来的代码。而Ioc与Factory比起来,Ioc的优点是更大的灵活性,通过配置可以控制很多注入的细节,而Factory模式,行为是相对比较封闭固定的,生产一个对象就必须接受它全部的特点,不管是否需要。其实轻量级和重量级都是相对的概念,使用资源更少、运行负载更小的自然就算轻量。

话题扯远了,因为Spring框架带来了太多可以探讨的地方。比如它的非侵入性:指的是它提供的框架实现可以让程序员编程却感觉不到框架的存在,这样所写的代码并没有和框架绑定在一起,可以随时抽离出来,这也是Spring设计的目标。Spring是唯一可以做到真正的针对接口编程,处处都是接口,不依赖绑定任何实现类。同时,Spring还设计了自己的事务管理、对象管理和Model2 的MVC框架,还封装了其他J2ee的服务在里面,在实现上基本都在使用依赖注入和AOP的思想。由此我们大概可以看到Spring是一个什么概念上的框架,代表了很多优秀思想,值得深入学习。笔者强调,学习并不是框架,而是框架代表的思想,就像我们当初学Struts一样……

1.Spring MVC
关于IoC和AOP笔者在上篇已经稍微解释过了,这里先通过Spring的MVC框架来给大家探讨一下Spring的特点吧。(毕竟大部分人已经很熟悉Struts了,对比一下吧)
众所周知MVC的核心是控制器。类似Struts中的ActionServlet,Spring里面前端控制器叫做DispatcherServlet。里面充当Action的组件叫做Controller,返回的视图层对象叫做ModelAndView,提交和返回都可能要经过过滤的组件叫做 Interceptor。

让我们看看一个从请求到返回的流程吧:
(1) 前台Jsp或Html通过点击submit,将数据装入了request域
(2) 请求被Interceptor拦截下来,执行preHandler()方法出前置判断
(3) 请求到达DispathcerServlet
(4) DispathcerServlet通过Handler Mapping来决定每个reuqest应该转发给哪个后端控制器Controlle
Java杂谈(十一)ORM
Java杂谈(十一)ORM

这是最后一篇Java杂谈了,以ORM框架的谈论收尾,也算是把J2ee的最后一方面给涵盖到了,之所以这么晚才总结出ORM这方面,一是笔者这两周比较忙,另一方面也想善始善终,仔细的先自己好好研究一下ORM框架技术,不想草率的敷衍了事。

其实J2ee的规范指南里面就已经包括了一些对象持久化技术,例如JDO(Java Data Object)就是Java对象持久化的新规范,一个用于存取某种数据仓库中的对象的标准化API,提供了透明的对象存储,对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。我们如果要理解对象持久化技术,首先要问自己一个问题:为什么传统的JDBC来持久化不再能满足大家的需求了呢?

笔者认为最好是能用JDBC真正编写过程序了才能真正体会ORM的好处,同样的道理,真正拿Servlet/Jsp做过项目了才能体会到Struts、 Spring等框架的方便之处。很幸运的是笔者这两者都曾经经历过,用混乱的内嵌Java代码的Jsp加Servlet转发写过完整的Web项目,也用 JDBC搭建过一个完整C/S项目的后台。所以现在接触到新框架才更能体会它们思想和实现的优越之处,回顾从前的代码,真是丑陋不堪啊。^_^

回到正题,我们来研究一下为什么要从JDBC发展到ORM。简单来说,传统的JDBC要花大量的重复代码在初始化数据库连接上,每次增删改查都要获得 Connection对象,初始化Statement,执行得到ResultSet再封装成自己的List或者Object,这样造成了在每个数据访问方法中都含有大量冗余重复的代码,考虑到安全性的话,还要加上大量的事务控制和log记录。虽然我们学习了设计模式之后,可以自己定义Factory来帮助减少一部分重复的代码,但是仍然无法避免冗余的问题。其次,随着OO思想深入人心,连典型的过程化语言Perl等都冠冕堂皇的加上了OO的外壳,何况是 Java中繁杂的数据库访问持久化技术呢?强调面向对象编程的结果就是找到一个桥梁,使得关系型数据库存储的数据能准确的映射到Java的对象上,然后针对Java对象来设计对象和方法,如果我们把数据库的Table当作Class,Record当作Instance的话,就可以完全用面向对象的思想来编写数据层的代码。于是乎,Object Relationship Mapping的概念开始普遍受到重视,尽管很早很早就已经有人提出来了。
缺点我们已经大概清楚了,那么如何改进呢?对症下药,首先我们要解决的是如何从Data Schema准备完美的映射到Object Schema,另外要提供对数据库连接对象生命周期的管理,对事务不同粒度的控制和考虑到扩展性后提供对XML、Properties等可配置化的文件的支持。到目前为止,有很多框架和技术在尝试着这样做。例如似乎是封装管理得过了头的EJB、很早就出现目前已经不在开发和升级了的Apache OJB、首先支持Manual SQL的iBATIS,还有公认非常优秀的Hibernate等等。在分别介绍它们之前,我还想反复强调这些框架都在试图做什么:

毕竟Java Object和数据库的每一条Record还是有很大的区别,就是类型上来说,DB是没有Boolean类型的。而Java也不得不用封装类(Integer、Double等)为了能映射上数据库中为null的情况,毕竟Primitive类型是没有null值的。还有一个比较明显的问题是,数据库有主键和外键,而Java中仍然只能通过基本类型来对应字段值而已,无法规定Unique等特征,更别提外键约束、事务控制和级联操作了。另外,通过Java Object预设某Field值去取数据库记录,是否在这样的记录也是不能保证的。真的要设计到完全映射的话,Java的Static被所有对象共享的变量怎么办?在数据库中如何表现出来……
我们能看到大量的问题像一座座大山横在那些框架设计者们面前,他们并不是没有解决办法,而是从不同的角度去考虑,会得到很多不同的解决方案,问题是应该采取哪一种呢?甚至只有等到真正设计出来了投入生产使用了,才能印证出当初的设想是否真的能为项目开发带来更多的益处。笔者引用一份文档中提到一个健壮的持久化框架应该具有的特点:
A robust persistence layer should support----
1. Several types of persistence mechanism
2. Full encapsulation of the persistence mechanism.
3. Multi-object actions
4. Transactions Control
5. Extensibility
6. Object identifiers
7. Cursors: logical connection to the persistence mechanism
8. Proxies: commonly used when the results of a query are to be displayed in a list
9. Records: avoid the overhead of converting database records to objects and then back to records
10. Multi architecture
11. Various database version and/or vendors
12. Multiple connections
13. Native and non-native drivers
14. Structured query language queries(SQL)
Java杂谈(十一) ORM
现在来简短的介绍一下笔者用过的一些持久化框架和技术,之所以前面强调那么多共通的知识,是希望大家不要盲从流行框架,一定要把握它的本质和卓越的思想好在哪里。
1. Apache OJB
OJB代表Apache Object Relational Bridge,是Apache开发的一个数据库持久型框架。它是基于J2ee规范指南下的持久型框架技术而设计开发的,例如实现了ODMG 3.0规范的API,实现了JDO规范的API, 核心实现是Persistence Broker API。OJB使用XML文件来实现映射并动态的在Metadata layer听过一个Meta-Object-Protocol(MOP)来改变底层数据的行为。更高级的特点包括对象缓存机制、锁管理机制、 Virtual 代理、事务隔离性级别等等。举个OJB Mapping的简单例子ojb-repository.xml:

<class-descriptor class=”com.ant.Employee” table=”EMPLOYEE”>
<field-descriptor name=”id” column=”ID”
jdbc-type=”INTEGER” primarykey=”true” autoincrement=”true”/>

<field-descriptor name=”name” column=”NAME” jdbc-type=”VARCHAR”/>
</class-descrptor>

<class-descriptor class=”com.ant.Executive” table=”EXECUTIVE”>
<field-descriptor name=”id” column=”ID”
jdbc-type=”INTEGER” primarykey=”true” autoincrement=”true”/>

<field-descriptor name=”department” column=”DEPARTMENT” jdbc-type=”VARCHAR”/>

<reference-descriptor name=”super” class-ref=”com.ant.Employee”>
<foreignkey field-ref=”id”/>
</reference-descriptor>
</class-descrptor>

2. iBATIS
iBATIS最大的特点就是允许用户自己定义SQL来组配Bean的属性。因为它的SQL语句是直接写入XML文件中去的,所以可以最大程度上利用到 SQL语法本身能控制的全部特性,同时也能允许你使用特定数据库服务器的额外特性,并不局限于类似SQL92这样的标准,它最大的缺点是不支持枚举类型的持久化,即把枚举类型的几个对象属性拼成与数据库一个字段例如VARCHAR对应的行为。这里也举一个Mapping文件的例子sqlMap.xml:
<sqlMap>
<typeAlias type=”com.ant.Test” alias=”test”/>

<resultMap class=”test” id=”result”>
<result property=”testId” column=”TestId”/>
<result property=”name” column=”Name”/>
<result property=”date” column=”Date”/>
</resultMap>

<select id=”getTestById” resultMap=”result” parameterClass=”int”>
select * from Test where TestId=#value#
</select>

<update id=”updateTest” parameterClass=”test”>
Update Tests set Name=#name#, Date=”date” where TestId=#testId#
</update>
</sqlMap>

3. Hibernate
Hibernate无疑是应用最广泛最受欢迎的持久型框架,它生成的SQL语句是非常优秀。虽然一度因为不能支持手工SQL而性能受到局限,但随着新一代 Hibernate 3.x推出,很多缺点都被改进,Hibernate也因此变得更加通用而时尚。同样先看一个Mapping文件的例子customer.hbm.xml来有一个大概印象:

<hibernate-mapping>
<class name=”com.ant.Customer” table=”Customers”>
<id name=”customerId” column=”CustomerId” type=”int” unsaved-value=”0”>
<generator class=”sequence”>
<param name=”sequence”> Customers_CustomerId_Seq </param>
</generator>
</id>

<property name=”firstName” column=”FirstName”/>
<property name=”lastName” column=”LastName”/>

<set name=”addresses” outer-join=”true”>
<key column=”Customer”/>
<one-to-many class=”com.ant.Address”/>
</set>
</class>
</hibernate-mapping>

Hibernate有很多显著的特性,最突出的就是它有自己的查询语言叫做HQL,在HQL中select from的不是Table而是类名,一方面更加面向对象,另外一方面通过在hibernate.cfg.xml中配置Dialect为HQL可以使得整个后台与数据库脱离耦合,因为不管用那种数据库我都是基于HQL来查询,Hibernate框架负责帮我最终转换成特定数据库里的SQL语句。另外 Hibernate在Object-Caching这方面也做得相当出色,它同时管理两个级别的缓存,当数据被第一次取出后,真正使用的时候对象被放在一级缓存管理,这个时候任何改动都会影响到数据库;而空闲时候会把对象放在二级缓存管理,虽然这个时候与数据库字段能对应上但未绑定在一起,改动不会影响到数据库的记录,主要目的是为了在重复读取的时候更快的拿到数据而不用再次请求连接对象。其实关于这种缓存的设计建议大家研究一下Oracle的存储机制(原理是相通的),Oracle牺牲了空间换来时间依赖于很健壮的缓存算法来保证最优的企业级数据库访问速率。

以上是一些Mapping的例子,真正在Java代码中使用多半是继承各个框架中默认的Dao实现类,然后可以通过Id来查找对象,或者通过 Example来查找,更流行的是更具Criteria查找对象。Criteria是完全封装了SQL条件查询语法的一个工具类,任何一个查询条件都可以在Criteria中找到方法与之对应,这样可以在Java代码级别实现SQL的完全控制。另外,现在许多ORM框架的最新版本随着JDk 5.0加入Annotation特性都开始支持用XDoclet来自动根据Annotation来生成XML配置文件了。

笔者不可能详细的讲解每一个框架,也许更多的人在用Hibernate,笔者是从OJB开始接触ORM技术的,它很原始却更容易让人理解从JDBC到 ORM的过渡。更多的细节是可以从官方文档和书籍中学到的,但我们应该更加看中它们设计思想的来源和闪光点,不是盲从它们的使用方法。

分享到:
评论
3 楼 lizhongnan 2008-12-11  
感觉这篇文章讲J2SE的比较独到,而后面J2EE没什么感觉,总体来说还是收获很大
2 楼 llly85 2008-12-10  
System.out.println("111111");
1 楼 llly85 2008-12-10  
很好 支持ing

相关推荐

    刘嘉怡.中期检查.doc

    刘嘉怡.中期检查.doc

    COMSOL热电效应模型:基于MATLAB API的热电转换仿真与优化

    内容概要:本文详细介绍了如何使用COMSOL Multiphysics进行热电效应仿真的全过程。首先解释了热电效应的基本概念及其应用场景,如手机充电发烫、吹风机温度升高等。接着,通过具体实例展示了如何在COMSOL中建立热电模型,包括选择合适的物理场(焦耳热和热电效应)、设定材料属性(电导率、导热系数、塞贝克系数)、绘制几何形状以及设置边界条件。文中还提供了详细的MATLAB代码片段用于自动化建模流程,涵盖求解器配置、网格划分、后处理等方面的技术细节。此外,作者分享了一些常见问题的解决方案,如求解器不收敛、网格畸变等。 适合人群:对热电效应感兴趣的科研人员、工程技术人员及高校学生,尤其适用于有一定COMSOL和MATLAB基础的学习者。 使用场景及目标:帮助读者掌握热电效应的基本原理和COMSOL仿真技能,能够独立完成从模型构建到结果分析的完整流程。目标是提高热电转换系统的效率,优化设计参数,探索新材料的应用潜力。 其他说明:文章不仅提供了理论指导,还包括大量实战经验和技术技巧,有助于解决实际建模过程中遇到的问题。

    汽车内外饰模具设计规范详解:分型面、斜顶滑块及模架顶出系统的技术要点

    内容概要:本文深入探讨了汽车内外饰模具设计的关键要素,涵盖分型面设计、斜顶和滑块的应用、模架选择以及顶出系统的配置。针对每个部分,不仅提供了理论指导,还辅以Python、MATLAB等编程语言的实际代码示例,帮助理解和实施具体设计方案。例如,分型面设计强调了如何根据产品结构和外观要求确定最佳分型面位置;斜顶和滑块部分讨论了不同类型及其应用场景;模架和顶出系统则关注于结构稳定性和顶出效果的优化。 适合人群:从事汽车模具设计的专业人士,尤其是希望深入了解内外饰模具设计细节的新手设计师和技术人员。 使用场景及目标:适用于汽车内外饰模具设计项目,旨在提高模具设计的精度和效率,减少试错成本,确保产品质量。通过学习本文提供的技术和实践经验,能够更好地应对实际工作中遇到的各种挑战。 其他说明:文中提到的代码示例和经验公式均来源于实际工程案例,具有较高的参考价值。同时,作者还分享了许多宝贵的行业经验和技巧,有助于读者快速掌握模具设计的核心技能。

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    【人工智能领域】DeepSeek AI深度探索平台的优势解析:多模态处理、低成本训练与广泛应用场景综述

    内容概要:DeepSeek AI是由杭州深度求索人工智能基础技术研究有限公司于2025年1月20日发布的深度探索AI技术。它具有多模态能力、多语言支持、长上下文理解、领域垂直优化、开源特性等多项技术突破,支

    IIS配置phpweb服务器所需VC-redist.x64.rar

    IIS配置phpweb服务器所需VC_redist.x64.rar

    云南移动5G-A网业战略发展探讨 -创新领航,千帆竞发,共同迈入5G-A新时代.pptx

    云南移动5G-A网业战略发展探讨 -创新领航,千帆竞发,共同迈入5G-A新时代.pptx

    C#学习之OpenCv实现模版匹配案例

    本文描述了如何使用C#基于OpenCvSharpe实现模版匹配功能,其中实现了下功能: 1、图像加载; 2、模版加载、绘制、保存功能; 3、模版匹配功能。

    【软件工程与数据分析】数据结构求职面试问题汇总:涵盖链表、树结构及算法复杂度分析的实战题目解析

    内容概要:本文档汇集了CSci 235软件设计与分析II课程中关于数据结构的面试题,由Stewart Weiss教授整理。文档涵盖了广泛的数据结构主题,包括但不限于链表(如单链表、双向链表、循环链表)、二叉树(如二叉搜索树、最小高度二叉搜索树)、栈、队列等。每个问题都旨在考察求职者对不同数据结构的理解及其应用场景。例如,选择合适的数据结构实现手机通讯录功能,或设计支持撤销功能的文本编辑器。此外,文档还探讨了复杂度分析(Big-O表示法),以及如何优化特定操作的时间复杂度。最后,文档提供了额外的学习资源链接,帮助求职者进一步准备面试。 适合人群:计算机科学专业的学生或有志于从事软件开发工作的求职者,特别是那些希望在技术面试中表现优异的人士。 使用场景及目标:①理解并掌握常见数据结构的基本概念和特性;②学会根据不同场景选择最合适的数据结构;③掌握常见数据结构操作的时间复杂度分析;④为技术面试做充分准备,提高面试成功率。 其他说明:文档中的问题不仅限于理论知识,还包括实际编码练习,建议读者在学习过程中动手实践,以加深理解和记忆。同时,文档提供的额外资源链接可以作为扩展阅读材料,帮助读者更全面地掌握相关知识。

    【路径规划】基于matlab A_Star融合灰狼算法GWO求解多仓库机器人送货路径规划【含Matlab源码 13134期】.zip

    Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    帆软本地打印插件FinePrint 8.0版本

    帆软本地打印插件FinePrint 8.0版本,适用于FineReport8

    【嵌入式控制系统】基于EECS461课程的嵌入式控制技术在汽车领域的应用与发展:从基础概念到未来挑战了文档的主要内容

    内容概要:本文介绍了密歇根大学EECS 461课程——嵌入式控制系统的核心内容及其发展背景。课程旨在教授学生嵌入式控制系统的理论与实践,包括传感器和执行器接口、实时性能和安全要求、混合行为系统、分布式控制网络等方面的知识。文中特别强调了现代汽车作为嵌入式控制系统的典型应用,从1977年到2019年间,汽车技术经历了从模拟控制到微处理器控制的巨大变革,如今的汽车具备了更高效、更环保、更安全的特点。课程还涵盖了S32K144微控制器的开发环境、实验室练习(如数字I/O、PWM信号生成、虚拟墙模拟等)以及自动代码生成工具的使用。 适合人群:具备一定编程基础,特别是对嵌入式系统感兴趣的本科生和研究生,尤其是电气工程、计算机科学专业的高年级学生或硕士生。 使用场景及目标:①了解嵌入式控制系统的基本概念和发展历程;②掌握嵌入式控制系统的设计方法和技术手段,如实时操作系统、中断处理、网络通信协议(CAN)等;③通过实际项目操作,熟悉嵌入式硬件平台和开发工具链的应用。 其他说明:随着汽车行业向智能化、自动化方向发展,对于能够开发复杂嵌入式软件的人才需求日益增长。EECS 461不仅为学生提供了扎实的技术训练,也为他们未来的职业发展打下了坚实的基础。此外,课程还反映了跨学科教育的重要性,鼓励学生打破传统学术界限,培养解决实际问题的能力。

    C#与Halcon联合编程实现高效视觉几何定位与测量框架

    内容概要:本文详细介绍了如何利用C#与Halcon联合编程构建高效的视觉几何定位与测量框架。主要内容涵盖模板创建与匹配、圆测量、数据持久化以及图像采集等方面的技术细节。首先,通过创建形状模板并进行匹配,实现了工件的精确定位。接着,针对圆形物体的测量,提出了动态ROI绘制、亚像素边缘提取和稳健圆拟合的方法。此外,还讨论了模板管理和图像采集的最佳实践,确保系统的稳定性和高效性。最后,强调了Halcon对象的内存管理和错误处理机制,提供了实用的优化建议。 适合人群:具备一定编程基础,尤其是对C#和Halcon有一定了解的研发人员和技术爱好者。 使用场景及目标:适用于工业生产线上的自动化检测设备开发,旨在提高工件定位和尺寸测量的精度与效率。主要目标是帮助开发者掌握C#与Halcon联合编程的具体实现方法,从而构建稳定可靠的视觉检测系统。 其他说明:文中提供了大量实战代码片段和调试技巧,有助于读者快速理解和应用相关技术。同时,作者分享了许多实际项目中的经验和教训,使读者能够避开常见陷阱,提升开发效率。

    【人工智能领域】DeepSeek AI核心技术优势及广泛应用场景:推动全球AI创新与产业变革

    内容概要:本文深入探讨了DeepSeek AI的独特优势及其在全球AI领域的影响力。DeepSeek由中国深度求索公司开发,自2025年1月20日发布以来,凭借其卓越的性能和独特优势迅速吸引了全球关注。其核心优势包括:1) 极致成本效率,如低成本训练和高效推理;2) 强大的推理能力,涵盖多领域表现优异

    php连接sqlserver之VC-redist.x64.exe

    php连接sqlserver之VC_redist.x64.exe

    基于Matlab/Simulink的异步电动机恒压频比与转差频率控制仿真及其实现

    内容概要:本文详细介绍了利用Matlab/Simulink进行异步电动机交流调速系统的仿真实验,主要探讨了两种控制方式:恒压频比(V/F)开环控制和转差频率闭环控制。文中不仅提供了具体的数学模型和代码片段,还展示了不同控制方式下的仿真结果对比,包括转速响应、电流波形和谐波含量等方面的表现。此外,文章深入讲解了SVPWM(空间矢量脉宽调制)的应用,强调了其相对于传统SPWM的优势,并给出了详细的参数调整技巧和注意事项。 适合人群:从事电机控制系统设计的研究人员和技术人员,尤其是对Matlab/Simulink有一定基础并希望深入了解异步电动机调速系统的人群。 使用场景及目标:适用于需要进行电机控制算法开发和优化的场合,旨在帮助读者掌握异步电动机调速的基本原理和具体实现方法,提高仿真的准确性和效率。 其他说明:文章通过丰富的实例和图表,生动地展示了各种控制策略的特点和效果,有助于读者更好地理解和应用相关理论。同时,文中提供的调试技巧对于解决实际工程中的常见问题非常有帮助。

    电动汽车等速工况续驶里程仿真及Matlab实现详解

    内容概要:本文详细介绍了如何利用Matlab进行电动汽车等速工况续驶里程的仿真。首先解释了等速工况的概念及其重要性,接着展示了具体的参数设定,如车辆质量、风阻系数、电池容量等。然后深入探讨了核心算法,包括阻力计算、功率需求、能量消耗以及SOC(剩余电量)的变化过程。文中特别强调了一些常见的陷阱和注意事项,如单位换算错误、电机效率的动态变化等。最后,通过可视化工具展示了仿真结果,并讨论了可能的改进方向,如引入NEDC工况循环和其他动态因素。 适合人群:新能源汽车专业的学生、研究人员以及对电动汽车仿真感兴趣的工程师。 使用场景及目标:①帮助理解和掌握电动汽车等速工况续驶里程仿真的原理和方法;②提供详细的代码实现和注释,便于学习和修改;③用于课程设计、毕业设计或其他研究项目。 其他说明:本文不仅提供了完整的Matlab代码,还包括详细的参数说明和常见问题解析,确保使用者能够顺利运行并理解整个仿真过程。同时,作者还分享了许多实践经验,有助于提高仿真的准确性和实用性。

    【定稿】桂林电子科技大学第七届大学生思政课社会实践优秀成果展示活动实施方案 (1).zip

    【定稿】桂林电子科技大学第七届大学生思政课社会实践优秀成果展示活动实施方案 (1).zip

    直线感应电机瞬态磁场仿真教程:Maxwell 16.0与ANSYS 2020关键技术解析

    内容概要:本文详细介绍了使用Maxwell 16.0和ANSYS 2020进行直线感应电机瞬态磁场仿真的方法和技术要点。首先强调了建模前的准备工作,包括初级线圈布置、次级导体材料选择、气隙宽度等参数的确定。然后针对Maxwell 16.0用户,讲解了坐标系的选择(笛卡尔坐标系)、初级绕组绘制、运动参数设置、网格剖分优化以及边界条件的正确配置。对于ANSYS 2020用户,则着重讲述了如何利用Maxwell模块建立模型并在Mechanical中进行电磁力耦合分析,包括参数化扫描设置、气隙厚度扫描、磁密云图动态更新等技巧。此外,文中还分享了许多实用的经验和注意事项,如避免常见的参数设置错误、提高仿真精度的方法、处理推力波动等问题的具体措施。 适合人群:从事电机设计与仿真的工程师、研究人员,尤其是有一定Maxwell和ANSYS使用基础的技术人员。 使用场景及目标:帮助用户掌握直线感应电机瞬态磁场仿真的全流程,确保仿真结果的准确性,提升工作效率。具体应用场景包括但不限于新电机设计验证、现有电机性能优化、故障诊断等。 其他说明:文中提供了大量具体的命令和脚本示例,便于读者直接应用到实际工作中。同时,作者结合自身丰富的实践经验,给出了许多宝贵的建议和警示,有助于读者避开常见陷阱,顺利完成仿真任务。

    基于Matlab Simulink的交流异步电机矢量控制与SVPWM仿真建模及优化

    内容概要:本文详细介绍了如何在Matlab Simulink中构建交流异步电机的矢量控制模型及其SVPWM调制方法。首先解释了坐标变换(如Clarke和Park变换)的基本原理,并提供了具体的实现代码。接着讨论了双闭环控制策略,即电流环和速度环的设计与参数整定,强调了PI控制器的抗饱和处理以及速度环带宽的选择。对于SVPWM部分,文章对比了几种不同的调制算法,推荐了一种改进的七段式算法,提高了电压利用率并降低了谐波含量。此外,文中还分享了许多实际调试过程中遇到的问题及解决方案,如启动电流冲击、低频振荡等。 适合人群:从事电力电子、电机驱动系统设计的研究人员和技术工程师,尤其是对矢量控制和SVPWM感兴趣的初学者。 使用场景及目标:适用于需要深入了解交流异步电机矢量控制原理及其实现方法的人群。目标是在掌握理论基础上,能够独立搭建并优化Simulink仿真模型,从而提高实际应用中的性能表现。 其他说明:随文提供的工程文件包含了完整的模型和详细的参数整定表格,便于读者进行实践操作。同时,作者还提供了一些实用的小贴士,帮助避免常见的错误和陷阱。

Global site tag (gtag.js) - Google Analytics