精通hibernate笔记_第1页
精通hibernate笔记_第2页
精通hibernate笔记_第3页
精通hibernate笔记_第4页
精通hibernate笔记_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

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

文档简介

1、第2章 java对象持久化技术概述2.1 直接通过jdbc api来持久化实体域对象1 实体域对象的持久化最终必须通过数据访问代码来实现,java应用访问数据库的最直接的方法就是通过jdbc api来访问数据库2 在java.sql包中常用的接口和类:drivermanager驱动程序管理器,负责创建数据库的连接connection:代表数据库的连接statement:负责执行sql语句preparestatement:负责执行sql语句,具有预定义sql语句的功能resultset:代表sql查询语句的查询结果集3 例子:class.forname(“com.mysql.jdbc.drive

2、r”);connection con = drivermanager.getconnection(dburl,dbuer,dbpwd);con.setautocommit(false);preparestatement pres = con.preparestatement(“insert into user (id,name) values(?,?)”);pres.setstring(1,”111”);pres.setstring(2,“test”);pres.execute();/resultset res = pres.executequery();mit();pres.close();

3、con.close();2.2 orm简介2.2.1对象-关系映射的概念1 orm解决的主要问题就是对象-关系映射,域模型和关系模型都是分别建立在概念模型的基础上,域模型是面向对象的,而关系模型是面向关系的。一般情况,一个持久化类对应一张表2.2.2 orm中间件的基本使用方法1 orm中间件采用元数据来描述对象-关系映射细节,元数据通常采用xml格式,并且存放在专门的对象-关系映射文件中2.2.3 常用的orm中间件hibernate,ibatis,toplink,jpa(java persistence api) java 持久化接口2.3 实体域对象的其他持久化模式orm模式,主动域对象

4、模式,jdo模式,cmp模式2.3.1 主动域对象模式1 主动域对象是实体域对象的一个形式,在它的实现中封装了关系数据模型和数据访问细节2 ejb分为:会话ejb(实现业务逻辑),实体ejb(代表业务实体)。实体ejb又分为:基于bmp的实体ejb(由ejb实现本身的数据访问细节)和基于cmp的实体ejb(由ejb容器实现数据访问细节)2.3.2 jdo模式1 jdo:java data object。是sun公司制定的描述对象持久化语义的标准api。2 四层应用结构:表述层,业务逻辑层,jdo api(sun公司制定),jdo实现(第三方提供),jdbc api2.3.3 cmp模式1 cm

5、p表示有ejb容器来管理实体ejb的持久化,ejb容器封装了对象-关系的映射以及数据访问细节2.4 hibernate api 简介1 hibernate api中的接口分类:a 提供访问数据库操作的接口:session,transaction,query接口b 用于配置hibernate的接口:configurationc 使用应用程序拦截hibernate内部发生的事件,并做出相关的回应:interceptor,loadeventlistener,saveeventlistener2 hibernate内部封装了jdbc,jta(java transaction api),jndi(jav

6、a naming and directory interface)。jdbc提供底层的数据库访问操作,jndi和jta是hibernate能够和javaee应用服务集成2.4.1 hibernate的核心接口1 5个核心接口:a configuration接口:配置hibernate,根启动hibernate,创建sessionfactory对象,hibernate应用通过configuration对象获得对象-关系映射文件中的元数据。b sessionfactory接口:初始化hibernate,充当数据存储源代理,创建session对象,一个sessionfactory对应一个数据储存源,

7、是线程安全的,是重量级的(需要很大的内存,存放预定义的sql数据已经映射元数据),用户可以给sessionfactory配置一个缓存插件,这缓存插件叫二级缓存,缓存被工作单元读过的数据c session接口,负责保存,更新,删除,加载和查询对象。不是线程安全的,是轻量级的。有一个缓存被称作hibernate第一缓存,存放当前工作单元加载的对象d transaction:管理事务e query和criteria接口:执行数据库查询。query实例包装了一个hql查询语句,hql语句是面向对象的,引用的是对象属性,不是表的字段。criteria完全封装了基于字符串形式的查询语句,比query更面向

8、对象,criteria接口擅长执行动态查询2.4.2 事件处理接口1 事件以及事件监听接口:加载对象触发loadevent事件,该事件有loadeventlister监听处理,保存对象触发saveevent该事件有saveeventlistener监听处理2 interceptor接口:2.4.3 hibernate映射类型接口org.hibernate.type.type接口表示hibernate映射类型,用于把域对象映射为数据库的关系数据hibernate为type接口提供各种实现类1 primitive类,映射java基本类型,包括:bytetype,shorttype,integert

9、ype,longtype,floattype,doubletype,charactertype,booleantype2 datetype:映射java日期类型3 binarytype:映射byte类型第3章 第一 hibernate应用1 在java应用中使用hibernate步骤:a 创建hibernate的配置文件b 创建持久化类c 创建对象-关系映射文件d 通过hibernateapi编写访问数据库的代码3.1创建hibernate的配置文件1 hibernate的配置文件有两种形式:a 一种是xml格式的文件b 一种是java属性文件,采用“健=值”的形式2 hibernate.pr

10、operties文件内容hibernate.dialect=org.hibernate.dialect.mysqldialecthibernate.connection.driver_class=com.mysql.jdbc.driverhibernate.connection.url=jdbc:mysql:/localhost:3036/sampledbhibernate.connection.username=roothibernate.connection.pasword=1234hibernate.show_sql=true3.2创建持久化类1 持久化的类是要hibernate持久化到

11、数据库中的类,持久化类满足javabean规范,有属性,以及属性的getxxx(),setxxx()方法,如果属性是boolean类型,前缀可以是get也可以是is。2 hibernate不要求持久化类必须实现java.io.serializable接口。但对于采用rmi或javaee分布式结构的java应用,需要在不同进程节点之间传输时,必须实现serializable接口。3 hibernate要求持久化类必须有默认的无参构造函数。hibernate通过反射机制,调用java.lang.reflect.constructor.newinstance()创建持久化类对象。一般默认构造函数的访

12、问级别可以是任何类型,但是为了让hibernate在运行的时候创建动态代理,访问级别就必须是public,protect或默认的,不可以是private3.3创建数据库schema3.4创建对象-关系映射文件<hibernate-mapping><class name=”com.mypack.customer” table=”customer”><id name=”id” column=”id” type=”long”><generator class=”increment”/></id><property name=”name

13、” column=”name” type=”string” not-null=”true”/></class></hibernate-mapping>3.4.1 映射文件的文档类型定义(dtd)1 顶层元素<hibernate-mapping>描述<!element hibernate-mapping(meta*,typeof*,import*,(class|subclass|joined-subclass|union-subclass)*,resultset*,(query|sql-query)*,filter-def*,database-ob

14、ject*)>2顶层元素<hibernate-mapping>的子元素<class>描述<!element class(meta*,subselect?,cache?,synchronize*,comment?,tuplizet*,(id|composite-id),discriminator?natrual-id?,(version|timestamp)?,(property|many-to-one|one-to-one|component|.)>3 dtd中特殊字符的作用无符号:该子元素在父元素内必须存在且只能存在一次+:该子元素在父元素内必须存在

15、,可以存在一次或多次*:该子元素在父元素内可以不存在,或0次或多次?:该子元素在父元素内存在0或多次id 在class中必须存在且只能存在一次property 在class里可以存在0次或多次在映射文件中,父元素中的各种子元素的定义必须符合特定的顺序3.4.1 把customer持久化类映射到customer表中1 <propert >中的type属性是指hibernate的映射类型。hibernate的映射类型是java类型和sql类型的桥梁。2 java类型,hibernate映射类型,sql类型之间的关系string -sting-varchar(n)int-int-intc

16、har -character-char(n)boolean-boolean-bitstring -text-textdate-date-datebyte-binary-blobtimestamp-timestamp-timestamp3 hibernate采用xml文件配置对象关系映射的优点:a: hibernate不会渗透到上层域模型中,也不会渗透到下层的关系数据模型中b: 域模型和关系数据模型彼此独立c:对象关系映射不依赖任何程序代码,如果需要修改对象关系模型,只需要修改xml文件就可以了3.5通过hibernate api操纵数据库3.5.1 hibernate的初始化1 初始化过程:a

17、 创建一个configuration类的实例,configuration类的构造方法把默认文件路径下的pertis配置文件中的配置信息读入到内存:configuration config =new configuration();b 调用configuration类的addclass(customer.class)方法:config.addclass(customer.class)该方法把默认文件路径下的customer.hbm.xml文件中的映射信息读入到内存中c 调用configuration类中的buildsessionfactory()方法:sessionfa

18、ctory = config.buildsessionfactory(); 该方法创建一个sessionfactory实例,并把configuration对象包含的信息复制到sessionfactory对象缓存中,sessionfactory代表一个数据库存储源,如果只有一个数据存储源,只要创建一个sessionfactory实例,当sessionfactory对象创建以后,该对象不和configuration对象关联,因此如果修改configuration对象,不会对sessionfactory有任何影响。如果对象的缓存很大,就称为重量级对象,如果对象占有内存空间小,就是轻量级对象。sess

19、ionfactory就是个重量级对象。2 sessionfactory的缓存可以分为两类:内置缓存和外置缓存(也称为二级缓存)。sessionfactory的内置缓存中存放了hibernate配置信息和映射元数据信息等。sessionfactory的位置缓存是一个可以配置的缓存插件,默认情况下sessionfactory不会启用这个缓存插件,外置缓存存放大量的数据库的拷贝,外置缓存的物理介质可以是内存或者硬盘。3.5.2 访问hibernate的session接口1 初始化结束后,就可以调用sessionfactory实例的opensession()方法来获得session实例,然后通过它就可

20、以执行访问数据库的操作,session接口提供了操作数据库的各种方法:如:a save()方法,把java对象保存到数据库b update()方法,更新数据库中的java对象c delete()方法,把特定的java对象从数据库中删除d load()或get()方法,从数据库中加载java对象注:在hibernate早期版本中,session接口还有一个用于查询java对象的find()方法,在hibernate3版本中,该find()方法已经被废弃,hibernate用query接口以及criteria接口来负责查询java对象。2 session是个轻量级的对象,通常将session实例与

21、一个数据事务绑定。每执行一个数据库事务,就应该创建一个新的session实例,不论事务执行成功与否,最后都要关闭session,调用close()方法,从而释放session实例中占有的资源。用transaction来控制事务。例如:session session= factory.opensession();transaction tx;try tx = session.begintransaction();.tmit();catch(runctime ex)if(tx!=null)tx.rollback();throw e;第四章 hbm2java和hbm2ddl工具1 hbm2java:

22、根据映射文件自动生成java源文件。2 hbm2ddl:根据映射文件自动生成数据库schema3 xdoclet:根据带有xdocle标记的java源文件生成映射文件4 middlegen:根据数据库schema自动生成映射文件。4.1创建对象-关系映射文件4.1.1 定制持久化类xxx.hbm.xml文件中的<meta>元素用于精粒度的控制java源代码的内容1 指定描述类的javadoc,如对于以下代码:<class name=”mypack.customer”><meta attribute=”class-description”>客户类autho y

23、hx</meta></class>生成的源代码:/*客户类*autho yhx*/2 指定类所继承的类,<class name=”mypack.customer”><meta attribute=”extends”>mypack.person</meta></class>生成的java源码:public class customer extends mypack.person implements serializablehibernate hbm2java工具自动使持久类实现java.io.serializable接口3

24、 指定描述类的属性的javadoc,<property name=”married” type=”boolean” column=”is_married”><meta attribute=”field-description”>is ths customer married</meta></property>表示married属性的getmarried()方法添加javadoc,生成的代码如下:/* is ths customer married*/public boolean getmarried()4 指定类,类的属性以及属性的getxx()

25、方法或setxx()方法的修饰符,可以选择的值包括:static ,final,abstract,public,protected,private<id name=”id”><meta attribute=”scope-set”>private</meta></id>5 指定在类的tostring()的方法,返回字符串中是否包含特定的属性<property name=”name” type=”string” not-null=”true”><meta attribute=”use-in-tostring”>true<

26、/meta></property>表示在tostring方法返回的字符串中包含name属性。6 <meta>元素的属性属 性 描述class-description 指定描述的javadocfield-description 指定类的属性的javadocinterface 如果为true,表示生成接口而非类,默认为falseimplements 指定类所实现的接口extends 指定类继承的父类名generated-class 重新指定生成的类名scope-class 指定类的修饰符,默认为publicscope-set 指定set的修饰符,默认publicsco

27、pe-get 指定get的修饰符,默认publicscope-field 指定类的属性的修饰符,默认publicuse-in-tostring 如果为true,表示在tostring方法返回值中包含该属性gen-property 如果是false,不会在java类<meta>元素是有作用范围的,如果在映射文件的开头声明了如下<meta>元素<hibernate-mapping><meta attribute=”extends”>mypack.businessobject</meta><class name=”mypac.mycl

28、ass1”>.</class><class name=”mypac.myclass2”>.</class></hibernate-mapping>那么映射文件中的所有类都继承了mypack.businessobjec类。如果只希望紧靠<meta>元素的元素的myclass1类继承mypack.businessobjec类,一种办法是把<meta>元素的inherit属性设为false;例如:<meta attribute=”extends” inherit=”false”>mypack.businesso

29、bject</meta>还有一种办法:<class name=”mypac.myclass1”><meta attribute=”extends” >mypack.businessobject</meta></class>4.1.2 定制数据库表<property>元素的<column>子元素用于精粒度的控制表的定义,1 设定字段名,字段长度及唯一性<class name=”mypac.myclass1”><meta attribute=”extends” >mypack.busines

30、sobject</meta><column name=”name” length=”50” not-null=”true” unique=”true”></column></class>2 设定字段不为空,并且为这个字段设立检查约束<class name=”mypac.myclass1”><meta attribute=”extends” >mypack.businessobject</meta><column name=”age” not-null=”true” check=”age>10” &g

31、t;</column></class>注意:<column>元素的所有属性都会影响hbm2ddl工具生成的ddl,但是只要not-null属性会影响hibernate的运行时行为。对于以上<column>元素,如果not-null属性为true,hibernate在保存customer对象时,会检验它的age是否为null,其他属性不会影响hibernate的行为,例如hibernate不会检验age是否大于103 设置索引,<class name=”mypac.myclass1”><meta attribute=”extend

32、s” >mypack.businessobject</meta><column name=”adddate” index=”idx_adddate” sql-type=”date”></column></class>4 设定字段的sql类型<class name=”mypac.myclass1”><meta attribute=”extends” >mypack.businessobject</meta><column name=”description” sql-type=”text”>&l

33、t;/column></class>如果没有设定sql-type属性,hbm2ddl工具会根据<property>元素的type属性所指定的hibernate映射类型来推断sql类型第五章 对象-关系5.1 持久话类在属性及访问方法1 持久化类使用javabean的风格,为需要被访问的属性提供getxxx()和setxxx()方法,这两个方法被称作持久化的访问方法。2 hibernate的应用中有,持久化类有两个跳用者a: java应用程序:调用对象的getxxx()方法,读取对象的信息,把它输入到用户界面,调用setxxx()方法,把用户界面输入的信息写入对象中

34、b:hibernate :调用对象的getxxx()方法,把它保存到数据库中,调用setxxx方法把数据库中的信息写入对象。确切的说,hibernate的session执行save(),update(),saveorupdate()方法的时候,调用对象的getxxx()方法,当session执行get(),load()方法,以及执行query方法的时候,调用setxxx()方法5.1.1 基本类型属性和包装类型属性5.1.2 hibernate访问持久化类属性的策略1 在对象-关系映射文件中,<property>元素的access属性,用于指定hibernate访问持久类属性的方式

35、,access属性值有两个:property:默认值,表明hibernate通过setxxx(),getxxx()方法来访问,持久化类每个属性都要提供setxxx(),getxxx()方法field:表明hibernate通过java反射机制来访问类的属性。如果类没有提供getxx(),setxx()方法,就把access属性设置为field。如:<property name=”name” access=”field”>除了把<property>属性设置为:property和field外,还可以自定义持久化类的属性访问方式。还要创建一个实现org.hibernate.p

36、roperty.propertyaccessor接口的类,然后把类的完整名字赋值给<property>的access属性。5.1.3 在持久化类的访问方法中加入程序逻辑1 在getxx()方法中加入程序逻辑。不管在持久类中是否存在name属性,只要在xxx.hbm.xml文件中映射了name属性,在hql语句中就可以访问它:from customer as c where =”name”在持久类中有的属性,在xxx.hbm.xml文件中没有映射,也不能访问。5.1.4 设置派生属性1并不是所有的持久化类的属性都直接和表的字段匹配,持久化类的有些属性必须在运行时通过计算才

37、能得出来,这个属性就称作派生属性。有两种解决方案:a:以customer类的avrprice属性为例,包括两步走:1 在映射文件中不映射avrprice属性2 在customer类的setorder()方法中加入程序逻辑,自动为avrprice属性赋值。b:利用<property>元素的formula属性,formula属性用来设置一个sql表达式的,hibernate根据它计算出派生属性 值。一下以customer类的totalprice属性为例。<property name=”totalprice” formula=”select sum(o.price) from or

38、der o where o.cursi_id=id”>3 用于控制insert和update语句的映射属性。<property> insert属性,如果为false,在insert语句中不包括该字段。默认为true<property>update属性,如果为false,在update语句中不包括该字段。默认为true<property>mutalbe属性,如果为false,等价所有的<property>元素的update属性为false,表示整个实例不能被更新。默认为true<property>dynamic-update属性,

39、如果为true,表示更新一个对象的时候,会动态的生成update语句,update语句中仅包含所有取值需要更新的字段。默认为false5.2 处理sql引用标识符在sql语法中,标识符是指用于为数据库表,试图,字段,或者索引等命名的字符串,常规标识符不包括空格,特殊字符,因此不用引用符合。5.3 创建命名策略一种是手工设置表名和字段名,一种是实现hibernate的org.hibernate.cfg.namingstrategy接口。对于这一个接口,hibernate已经有两个实现org.hibernate.cfg.defaultnamingstrategy和org.hibernate.cfg

40、.improvednamingstrateg5.4 设置数据库模式<hibernate-mapping schema=”schemal”>5.5 设置包名称<hibernate-mapping package=”mypack”>第六章 映射对象标识符6.1 关系数据库按主键区分不同记录。6.1.1 把主键定义为自动增长标识符类型mysql:auto_incrementsqlserver:identity6.1.2 从序列中(sequence)中获取自动增长的标识符。oracle:create sequence customer_id _sequence incremen

41、t by 2 start with 1;6.2 java语言按内存地址区分不同的对象6.3 hibernate用对象标识符(oid)来区分对象1 与表的主键对应,oid也是整数类型,hibernate允许在持久化类中把oid定义为以下类型:short:两个字节int:4个字节long:8个字节为了保证持久化对象的oid的唯一性和不可变性,通常由hibernate或底层数据库来给oid赋值,因此,可以把持久类的oid的setid()方法设为private类型。在对象-关系映射文件中,<id>元素来设置对象标识符。<id name=”id” type=”long” column=

42、”id”><generator class=”increment”/></id><generator>子元素用来设定标识符生成器,hibernate提供了生成器接口:org.hibernate.id.identitygenertor接口。并提供了多种内置的实现。org.hibernate.id.identirygenerator和org.hibernate.id.incrementgenertor.,他们的缩写为:identity和increment。2 hibernate提供的内置标识符生成器increment:适用代理主键,由hibernate自动

43、以递增的方式生成标识符,每次增量为1identity: 适用代理主键,由底层数据库生成标识符,前提底层数据库支持。db2,mysql,sqlserber,sybase,hypersonicsqlsequence: 适用代理主键,hibernate根据底层数据库生成标识符。前提底层数据库支持。db2,oracle,sapdbhilo: 适用代理主键,hibernate根据high/low算法来生成标识符。native: 适用代理主键,根据底层数据库自动生成标识符的支持能力,来选择identity,sequence,hilo.assigned:适用自然主键,由java负责生成标识符。为了能让jav

44、a程序能设置id,不能把setid()方法设置为private,应尽量避免使用自然主键。select:适用遗留数据库中的代理主键和自然主键,有数据库的触发器生成标识符foreign:用一个关联对象的标识符来做当前对象的标识符,主要适用一对一关联的场合。6.4 hibernate的内置标识符生成器的用法6.4.1 increment标识符生成器适用范围:1 由于increment不依赖底层的数据库,因此它适用所有的数据库系统2 适用于只有单个hibernate应用的进程访问同一个数据库的场合,在集群环境下不推荐使用3 oid必须是long,int或者short类型,如果把oid改为byte类型,

45、在运行时会抛出异常。6.4.2 identity标识符生成器<geranator class=”identity” />6.4.3 sequence标识符生成器<gernator class=”squenece”><param name=”squence”>test_id_seq </param></gernator>6.4.4 hilo标识符生成器6.4.5 native标识符生成器6.5 映射自然主键自然主键就是有业务含义的主键,在数据库设计中尽量避免使用自然主键。6.5.1 映射单个自然主键1例如在customer类中不定义id

46、属性customer类 oid为name属性时:<id name=”name” column=”name” type=”string”><generator class=”assigned”/><id><version name=”version” column=”version” unsaved-value=”null”>标识符生成策略为“assigned”,表示由应用程序为name赋值,不管customer对象是临时对象,还是游离对象,name属性永远不会为null。因此session的saveorupdate方法无法通过name属性是否为n

47、ull来确定customer对象状态,在这种情况下,可以设置<version>版本控制元素的unsaved-value属性,如果customer对象的version属性为null,就表示临时对象,否则为游离对象。在customer类中有一个version属性,在customer表中有version字段。2 如果customer对象中没有定义version版本控制属性,可以用下面两个方法解决:a:避免使用saveorupdate方法,保存customer临时对象时,调用session的save方法,如果保存customer游离对象时就用update方法。b:使用hibernate的拦

48、截器(interceptor),在interceptor实现类的isunsaved()方法中区分,是游离对象还是临时对象。6.5.2 映射复合自然主键1 如果customer类是以name和companyid为复合主键。则:<composite-id><key-property name=”name” column=”name” type=”string”/><key-property name=”companyid” column=”companyid” type=”string”/><version name=”version” column=”v

49、ersion” unsaved-value=”null” /></composite-id>注意:为了能使以上的session的get()方法正常运行,要求customer对象必须实现serializable接口,并且重新定义equals(),hashcode()方法。equals()方法判定两个对象是否相等条件是name和companyid都相等。2 映射复合主键的另外一种方式是先定义单独的主键类。例如上面例子:public class customerid implements serializableprivate final string name;private f

50、inal string companyid;.customer对象定义一个customerid变量,映射文件如下:<composite-id name=”customerid” class=”mypack.customerid”><key-property name=”name” column=”name” type=”string”/><key-property name=”companyid” column=” companyid” type=”string”/><version name=”version” column=”version” unsaved-value=”null”></composite-id>第七章 映射一对多关系7.1 建立多对一的单向关联关系1 <many-to-one>元素建立了customer属性和orders表的外键customer_id之间的映射。<many-to-one name=”customer” column=”customer_id”class=”com.mypack.customer”not-null=”true”lazy=”false”>name:设定待映射的

温馨提示

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

评论

0/150

提交评论