Hibernate重构Model模块_第1页
Hibernate重构Model模块_第2页
Hibernate重构Model模块_第3页
Hibernate重构Model模块_第4页
Hibernate重构Model模块_第5页
已阅读5页,还剩56页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、模块模块1 Hibernate1 Hibernate重构重构ModelModel模块模块项目六项目六 网上商城框网上商城框架模式的重构架模式的重构2模块目标“Hello World”应用Hibernate体系结构Hibernate核心编程接口基本配置高级配置3HIBERNATE概述 2-12001年末,Hibernate 1.0发布2003年6月8号,Hibernate 2发布,为Hibernate奠定成功的基石2003年末,Hibernate获得了Jolt 2004大奖以及被著名开源组织JBOSS收纳,这两个事件确立了Hibernate在Java ORM架构中的主导地位,甚至使之成为事实上的

2、工业标准4HIBERNATE概述 2-22004年,Hibernate的作者Gavin King加入EJB3标准委员会,参与EJB3规范的制定2005年3月,Hibernate 3正式发布,再次将Hibernate提升到了一个前所未有的高度,更加丰富和完善的数据库支持、实体属性的延迟加载、对存储过程和自定义持久化实现的支持使得Hibernate的灵活性和可扩展性进一步增强5“HELLO WORLD”应用 16-1一个简单的Hibernate应用,目标是:保存一个“Hello World”消息到数据库中,然后从数据库里取出该条消息并显示出来。应用由一个持久类Message和一个映射文件组成Mes

3、sage用来表示那些可打印的消息。Message类内容如下:6“HELLO WORLD”应用 16-27“HELLO WORLD”应用 16-3Message类有三个属性:标识符属性、消息文本、到另一个Message的引用。标识符属性很特殊,允许应用访问数据库表行的主键值。如果Message类的两个实例具有同样的标识符值,它们就代表数据库中的同一行。这里,标识符属性的类型为Long,实际上可以是任意类型8“HELLO WORLD”应用 16-4Message类的所有属性都有JavaBean风格的setter/getter方法,有一个无参的构造函数Message类的实例可以被Hibernate管

4、理,也可以不被管理因为Message对象不实现任何Hibernate特定的类或者接口,因此我们可以象使用其它Java类一样来使用它。例如:Message message = new Message(Hello World);System.out.println( message.getText() );9“HELLO WORLD”应用 16-5保存一个新的Message对象到数据库中去(假设MESSAGES表已经存在):Session session = getSessionFactory(). openSession();Transaction tx = session.beginTrans

5、action();Message message = new Message(Hello World);session.save(message);mit();session.close(); insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)values (1, Hello World, null)10“HELLO WORLD”应用 16-6我们从SQL语句看到,MESSAGE_ID 字段的值被设置为一个陌生的值,但我们并没有在任何地方设置message的id属性的值,它应该为null才对,为什么会出现这种情况?因

6、为id属性是一个特殊的标识符属性,它保存一个由系统产生的唯一值。当save()方法被调用的时候,这个值被Hibernate赋值给Message实例11“HELLO WORLD”应用 16-7下面的代码从数据库中取回所有的消息并打印到控制台上:Session newSession = getSessionFactory().openSession();Transaction newTransaction = newSession.beginTransaction();List messages = newSession.find(from Message as m order by m.text

7、 asc);System.out.println( messages.size() + message(s) found: );for ( Iterator iter = messages.iterator(); iter.hasNext(); ) Message message = (Message) iter.next(); System.out.println( message.getText() );newTmit();newSession.close(); 12“HELLO WORLD”应用 16-8字符串“from Message as m order by m.text asc”

8、是一个Hibernate查询,使用的是Hibernate自己的面向对象的查询语言HQL(Hibernate Query Language )。当find()方法被调用的时候,这个查询在Hibernate内部被翻译成下面的SQL语句:select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_IDfrom MESSAGES morder by m.MESSAGE_TEXT asc 13“HELLO WORLD”应用 16-9为了使上面的魔术能够发生,Hibernate需要关于Message类应该如何被持久化的更多的信息,这个信息通常以一个XML映射文档

9、的形式提供,这个映射文档定义了Message类的属性如何映射到MESSAGES表的字段该映射文档的内容如下:14“HELLO WORLD”应用 16-1015“HELLO WORLD”应用 16-11映射文档告诉Hibernate:Message类被持久化到MESSAGES表,标识符属性映射到MESSAGE_ID字段,text属性映射到MESSAGE_TEXT字段,nextMessage属性是一个many-to-one 重数的关联,映射到NEXT_MESSAGE_ID 字段16“HELLO WORLD”应用 16-12下面的代码改变我们的第一个message,然后创建一个新的message,并

10、和第一个message关联在一起:17“HELLO WORLD”应用 16-13上面的代码在一个事务里调用了3条SQL语句:select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_IDfrom MESSAGES mwhere m.MESSAGE_ID = 1insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)values (2, Take me to your leader (please), null)update MESSAGESset MESSAGE_TEXT =

11、Greetings Earthling, NEXT_MESSAGE_ID = 2where MESSAGE_ID = 1 18“HELLO WORLD”应用 16-14注意Hibernate如何检测到第一个message的text属性和nextMessage属性被修改并且自动地更新数据库。我们利用了Hibernate的一个特色,叫做自动脏数据检查(automatic dirty checking):当我们在一个事务里修改了一个对象的状态时,这个特色明确地要求Hibernate更新数据库来保存我们的成果19“HELLO WORLD”应用 16-15类似地,你可以看到,当从第一个message对象

12、创建一个引用时,这个新的message对象被持久化,这个特色被叫做级联保存(cascading save):只要通过一个已经被持久化的对象获得一个新的对象,Hibernate会调用save()方法来持久化这个新对象20“HELLO WORLD”应用 16-16SQL语句的顺序和我们设置属性值的顺序是不一样的。Hibernate使用一种算法来决定一个有效的顺序以避免数据库外键约束违例,这个特色被叫做transactional write-behind21HIBERNATE体系结构 2-1下图显示了Hibernate中最重要的接口:22HIBERNATE体系结构 2-2上图中的接口大致可分成以下几

13、类:被应用程序调用来执行基本的CRUD和查询操作的接口。它们包括Session、 Transaction和Query被应用程序调用来配置Hibernate的接口,主要是Configuration类回调接口,允许应用程序对Hibernate中发生的事件起反应。包括Interceptor、Lifecycle和Validatable对Hibernate的映射功能进行扩展的接口,包括UserType、CompositeUserType和IdentifierGenerator23核心接口 5-1Session(会话)Session不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connecti

14、on和Transaction之间Session也称为持久化管理器,因为它是与持久化有关的操作接口Session通过SessionFactory打开,在所有的工作完成后,需要关闭它与Web层的HttpSession没有任何关系24核心接口 5-2SessionFactory应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。通常情况下,整个应用只有唯一的一个会话工厂例如在应用初始化时被创建。然而,如果你使用Hibernate访问多个数据库,你需要对每一个数据库使用一个会话工厂会话工厂缓存了生成的SQL语句和Hibernate在运行时使用

15、的映射元数据25核心接口 5-3ConfigurationConfiguration 类负责管理Hibernate 的配置信息。它包括如下内容:Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等Hibernate映射文件(*.hbm.xml)应用程序使用一个Configuration实例来指定映射文件的位置、Hibernate特定的属性并创建SessionFactory26核心接口 5-4Transaction(事务)它将应用代码从底层的事务实现(可能是一个JDBC事务,一个JTA用户事务)中抽象出来,允许应用通过一组一致的AP

16、I控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)27核心接口 5-5QueryQuery(查询)接口允许你在数据库上执行查询并控制查询如何执行。查询语句使用HQL或者本地数据库的SQL方言编写28回调接口当一个对象上面发生了一些令人感兴趣的事情时,回调接口允许应用接收一个通知。例如,当一个对象被装载、被保存、被删除的时候Lifecycle和Validatable接口允许一个持久对象对关联到其自身的persistence lifecy

17、cle事件起反应Interceptor接口允许应用处理回调,而不强迫持久类去实现特定的Hibernate接口。该接口的实现被作为参数传递给持久类的实例29类型接口一个Hibernate的Type对象映射一个Java类型到一个数据库字段类型持久类的所有持久属性,包括关联,都有一个相应的Hibernate类型内置的Hibernate类型包括所有的Java基本数据类型以及许多JDK类型,如java.util.Currency、java.util.Calendar、byte UserType和CompositeUserType接口允许你定义自定义类型30扩展接口 2-1Hibernate提供的许多功能

18、都是可配置的,允许你在某些内置的策略之间进行选择。当内置的策略不满足要求时,Hibernate通常让你通过实现一个接口来插入你自己的定制实现扩展点包括:Primary key generation (IdentifierGenerator interface) SQL dialect support (Dialect abstract class) Caching strategies (Cache and CacheProvider interfaces)31扩展接口 2-2JDBC connection management (ConnectionProvider interface) T

19、ransaction management (TransactionFactory, Transaction, and TransactionManagerLookup interfaces) ORM strategies (ClassPersister interface hierarchy) Property access strategies (PropertyAccessor interface) Proxy creation (ProxyFactory interface)32配置环境 2-1在Hibernate的配置过程中,区分受管环境和非受管环境受管环境(Managed envi

20、ronment):具有池资源(例如,数据库连接池),并提供声明式的事务和安全服务。J2EE应用服务器,例如JBoss、BEA WebLogic、IBM WebSphere就实现了标准的受管环境33配置环境 2-2非受管环境(Non-managed environment):借助线程池提供基本的并发管理。不提供自动的事务、安全或资源管理一个servlet容器如Tomcat为Java Web应用提供一个非受管环境。一个独立的桌面应用或者一个命令行应用也被看作是非受管的34创建SESSIONFACTORY 6-1 不管处于什么环境,你必须做的第一件事情是开始Hibernate。这件事很容易:从一个C

21、onfiguration创建一个SessionFactory 为了创建一个SessionFactory,你首先在应用初始化期间创建一个Configuration的实例,并用它来设置映射文件的位置。然后再用它来创建SessionFactory。在SessionFactory被创建出来之后,你就可以抛弃掉这个Configuration类35创建SESSIONFACTORY 6-2下面就是开始Hibernate的代码:Configuration cfg = new Configuration();cfg.addResource(hello/Message.hbm.xml); cfg.setPrope

22、rties( System.getProperties() );SessionFactory sessions = cfg.buildSessionFactory();映射文件“Message.hbm.xml”的位置是相对于应用的classpath的根来确定的。例如,如果classpath是当前目录,Message.hbm.xml就必须在hello目录中。XML映射文件必须放置在classpath中36创建SESSIONFACTORY 6-3在该例子里,使用了JVM的系统属性来设置所有其它的配置选项根据惯例,Hibernate的XML映射文件以“.hbm.xml”为扩展名另一个惯例是,每个类有

23、一个映射文件,而不是所有的类共用一个映射文件Hibernate文档推荐每个持久类的映射文件与该类放在同一个目录里37创建SESSIONFACTORY 6-4如果你遵循了以上惯例,那么当你加载多个映射文件时,你可以用addClass()方法来替换addResource()方法:38创建SESSIONFACTORY 6-5上面例子的代码写法称作方法链(Method chaining ),这种编程风格被许多Hibernate接口支持由于SessionFactory是线程安全的,可由多个线程并发调用,大多数情况下,一个应用中针对一个数据库共享一个SessionFactory实例即可如果应用中需要访问多

24、个数据库,那么针对每个数据库,应分别为其创建对应的SessionFactory实例39创建SESSIONFACTORY 6-6Hibernate有2个配置文件:hibernate. properties 和 hibernate.cfg.xml ,可以任选一个使用在所有的配置选项中,数据库连接设置是最重要的。在受管环境和非受管环境中,它们的设置是不同的40在非受管环境中配置 7-1图2.2显示了在一个Web应用的运行环境中,一个JDBC连接池的角色:41在非受管环境中配置 7-2因为非受管环境不实现连接池,应用必须实现它自己的连接池或者依赖第三方的连接池,如开源的C3P0连接池如果没有Hiber

25、nate,应用代码经常调用连接池来获得JBDC连接并执行SQL语句有了Hibernate,上图就发生了改变,如图2.3所示:42在非受管环境中配置 7-3Hibernate作为JDBC连接池的客户。应用代码使用Hibernate的Session和Qurey API进行持久化操作,并且仅仅只需要使用Transaction API管理数据库事务43在非受管环境中配置 7-4使用连接池Hibernate提供了一个插件结构允许和任何连接池集成,并内置了对C3P0的支持Hibernate用一些特定的属性来配置连接池。在perties 文件中配置C3P0的代码如下所示:44在非受

26、管环境中配置 7-5从第一行开始,各行含义如下:1.JDBC驱动程序类名2.JDBC URL,指定主机名和数据库名3.数据库用户名4.用户密码5.数据库方言。因为不同数据库的SQL语句实现同标准的SQL都有些差别,Hibernate可以根据指定的方言把标准的SQL语句翻译成特定数据库的SQL语句来执行。Hibernate对所有流行的SQL数据库提供了内置的支持45在非受管环境中配置 7-66.C3P0连接池中JDBC连接的最小数量7.C3P0连接池中JDBC连接的最大数量。如果运行时该数量被耗尽,将会抛出异常8.超时时间。超过该时间后,一个空闲的连接将会从池中删除9.Prepared语句可以被

27、缓存的最大数量10.在一个连接自动生效之前的空闲时间,以秒为单位46在非受管环境中配置 7-7Hibernate支持的其它连接池是Apache DBCP 和 Proxool。Hibernate社区更喜欢C3P0和ProxoolHibernate也提供一个默认的连接池。这个连接池只适合于测试和试验,不适合用在产品当中47在受管环境中配置 4-1一个受管环境处理某些横切关注点,例如安全、连接池和事务管理。J2EE应用服务器是典型的受管环境。虽然应用服务器一般被设计用来支持EJB,但是,即使你不使用EJB实体Bean,你仍然可以利用它提供的其它管理服务Hibernate经常和会话Bean和消息驱动B

28、ean一起使用,如图2.4所示:48在受管环境中配置 4-2应用服务器把一个连接池作为一个绑定到JNDI的数据源暴露给应用。你需要指定一个JNDI名字来告诉Hibernate在哪里找到这个数据源。配置文件示例如下:49在受管环境中配置 4-3第一行是数据源的JNDI名字,数据源必须在应用的部署描述符中配置。第二行使Hibernate与JTA集成,第三行定位应用服务器的TransactionManager ,第四行指明数据库方言50在受管环境中配置 4-4Tomcat不是一个应用服务器,它只是一个servlet容器,虽然它有某些通常只在应用服务器中才能找到的特色。能被Hibernate使用的特色

29、之一是Tomcat连接池。Tomcat内部使用DBCP连接池但是把它作为一个JNDI数据源暴露,就象一个真的应用服务器一样。通过设置hibernate.connec-tion.datasource 属性,可以让Hibernate使用这个数据源。注意,Tomcat不提供一个事务管理器51高级配置设置 8-1在所有的配置参数中,有一个参数很重要:设置hibernate.show_sql =true可以使得所有产生的SQL语句被打印到控制台。通过它你可以进行错误检查和性能调整使用XML配置文件你可以使用hibernate.cfg.xml文件来完整地配置一个SessionFactory。不像hiber

30、perties文件只包含配置参数,hibernate.cfg.xml文件还可以指定映射文件的位置配置示例:52高级配置设置 8-253高级配置设置 8-3文档类型声明可选的name属性,相当于属性hibernate.session_ factory_name ,被用来把SessionFactory绑定到JNDIHibernate属性可以不用Hibernate前缀来指定映射文档可以被作为应用资源来指定54高级配置设置 8-4用上述配置,你可以用以下代码来初始化Hibernate:SessionFactory sessions = new Configuration().confi

31、gure().buildSessionFactory();Hibernate怎么知道配置文件放在哪呢?原来,当configure()被调用的时候,Hibernate自动在classpath中查找hibernate.cfg.xml文件如果你希望使用一个不同的文件名或者让Hibernate在一个子目录中查找,你必须传递一个路径参数给configure()方法:55高级配置设置 8-5SessionFactory sessions = new Configuration() .configure(/hibernate-config/auction.cfg.xml) .buildSessionFactory();如果在classpath中既有hibernate.cfg.xml文件,又有hibernat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论