第9章Hibernate框架高级应用1_第1页
第9章Hibernate框架高级应用1_第2页
第9章Hibernate框架高级应用1_第3页
第9章Hibernate框架高级应用1_第4页
第9章Hibernate框架高级应用1_第5页
已阅读5页,还剩53页未读 继续免费阅读

下载本文档

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

文档简介

1、第九章第九章 Hibernate高级应用高级应用9.1 Hibernate的单向关联映射9.2 Hibernate的双向关联映射9.3 数据查询方式9.1 Hibernate的关联映射 l通过Hibernate的支持,应用程序可以从底层的JDBC中释放出来,以面向对象的方式进行数据库访问。l但面向对象的内容远不止这些,比如对象和对象之间的关联关系,这对于客观世界的建模是非常重要的。lHibernate还完全可以理解面向对象的继承、多态等概念,一旦建立了正确继承映射,程序就能以更加面向对象的方式访问数据库。9.1 Hibernate的关联映射l客观世界中的对象,很少有孤立存在的。例如老师,往往与

2、被授课的学生存在关联关系。l如果已经得到某个老师的实例,那么应该可以直接获取该老师对应的全部学生;l反过来,如果已经得到一个学生的实例,也应该可以访问该学生对应的老师。l这种实例之间的互相访问就是关联关系。l关联关系是面向对象分析、设计最重要的知识,Hibernate完全理解这种关联关系,如果映射得当,Hibernate的关联映射将大大简化持久层数据的访问。9.1 Hibernate的关联映射l关联关系大致有如下分类l单向关系:l只需单向访问关联端,例如只能通过老师访问学生端,或者只能通过学生访问老师端l单向1-1l单向1-Nl单向N-1l单向N-Nl双向关系:l关联的两端可以互相访问,例如老

3、师和学生之间可以互相访问。l双向1-1l双向1-Nl双向N-N9.1.1 单向N-1关联l单向N-1(比如,多个人对应同一个住址)l只需从人实体端可以找到对应的地址实体,无需关心某个地址的全部住户。l为了让两个持久化类支持这种关联映射,程序应该在N的一端的持久化类中增加一个属性,该属性引用1的一端的关联实体。l(N-1nojointable)lPerson.javalAddress.javalPerson.hbm. xml lAddress.hbm.xml9.1.1 单向N-1关联lPerson.javapackage org.crazyit.app.domain;public class P

4、erson/标识属性private Integer id;/Person的name属性private String name;/保留Person的age属性private int age;/引用关联实体的属性private Address address;public void setId(Integer id) this.id = id;public Integer getId() return this.id;/其他属性的set方法和get方法9.1.1 单向N-1关联lAddress.javapublic class Address/标识属性private Integer address

5、Id;/地址详细信息private String addressDetail;/无参数的构造器public Address() /初始化全部属性的构造器public Address(String addressDetail) this.addressDetail = addressDetail; /属性的setter和getter方法一、无连接表的一、无连接表的N-1关联关联Person.hbm.xml文件文件Hibernate使用元素映射N-1的关联实体,直接采用元素来映射关联实体将会在N的一端的数据表中增加一个外键列,用于参照主表记录系统将先自动级联插入主表记录,即先持久化Address对

6、象,再持久化Person对象Address.hbm.xml文件文件Address类的映射文件无需任何改变持久化代码持久化代码private void testPerson()Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();/创建一个Person对象Person p = new Person();/创建一个瞬态的Address对象Address a = new Address(“Guangzhou); /设置Person的Name为Yeeku字符串p.setN

7、ame(Yeeku);p.setAge(29);/设置Person和Address之间的关联关系p.setAddress(a);/持久化Person对象session.persist(p);/创建一个瞬态的Address对象Address a2 = new Address(“Shanghai); /修改持久化状态的Person对象p.setAddress(a2); /mit();HibernateUtil.closeSession();系统准备保存Person对象,系统将要向person_inf表中插入一条记录但该记录参照的主表记录还不曾保存(被参照的Address实体还处于瞬态)结果如何?将

8、瞬态的Address对象关联到持久化状态下的Person对象;系统将会持久化Address对象,并建立Address对象与Person对象之间的关联。即先执行“insert into address_inf”,再执行“update person_inf” ,修改该Person对应的外键值Hibernate: insert into address_inf (addressDetail) values (?)Hibernate: insert into person_inf (name, age, address_id) values (?, ?, ?)Hibernate: insert int

9、o address_inf (addressDetail) values (?)Hibernate: update person_inf set name=?, age=?, address_id=? where person_id=?Hibernate控制台显示信息:控制台显示信息:查询查询MySQL数据库中的相关数据表数据库中的相关数据表9.1.1 单向N-1关联l有连接表的N-1关联(例子:N-1withjointable)l显式使用元素,该元素用于强制将一个类的属性映射到多张表中,通常也用于强制使用连接表ltable属性:用于指定连接表的表名l:映射连接表中参照本表主键的外键列l:映射

10、连接表中参照关联实体的外键列person.hbm.xml在这种映射策略下,person_id既作为外键列参照person_inf表的person_id主键列,也作为person_address连接表的主键列。从而保证了person_address数据表中person_id列不能出现重复值,即保证了一个Person实体最多只能关联一个Address实体。Hibernate: insert into address_inf (addressDetail) values (?)Hibernate: insert into person_inf (name, age) values (?, ?)Hib

11、ernate: insert into person_address (address_id, person_id) values (?, ?)Hibernate: insert into address_inf (addressDetail) values (?)Hibernate: update person_address set address_id=? where person_id=?Hibernate控制台显示信息:控制台显示信息:MySQL控制台查询结果控制台查询结果9.1.2单向单向1-1关联关联l从持久化类上来看,单向1-1与单向N-1关系没有丝毫区别l因为N的一端或者1的

12、一端都是直接访问关联实体l只需增加关联实体属性的set和get方法。l为元素增加unique=“true”,用以表示N的一端必须唯一l三类单向1-1关联l基于外键的单向1-1l有连接表的单向1-1l基于主键的单向1-19.1.2单向单向1-1关联关联l基于外键的单向1-1(例子:1-1FK)映射文件Person.hbm.xmlHibernate: insert into address_inf (addressDetail) values (?)Hibernate: insert into person_inf (name, age, address_id) values (?, ?, ?)H

13、ibernate: insert into address_inf (addressDetail) values (?)Hibernate: update person_inf set name=?, age=?, address_id=? where person_id=?Hibernate控制台显示信息:控制台显示信息:MySQL控制台查询结果:控制台查询结果:在address_id列增加唯一约束,形成单向1-1关联9.1.2单向单向1-1关联关联l有连接表的单向1-1l将有连接表的N-1中的元素增加unique=“true”属性即可。9.1.2单向单向1-1关联关联l基于主键的单向1-1

14、l基于主键关联的持久化类不能拥有自己的主键生成器策略,它的主键由关联实体来负责生成l使用元素来映射关联实体address当采用这种关联映射策略时,person_inf表将作为从表,address_inf表作为主表。此时person_inf表的主键将没有自己的主键生成策略,因为person_inf表里记录的主键将会与主表(address_inf)里的记录保持一致。9.1.3 单向单向1-N关联关联l单向1N的持久化类发生了改变,持久化类里需要使用集合属性。l1的一端需要访问N的一端,而N的一端将以集合(Set)形式表现l使用lclass属性:指定关联实体的类型,默认通过反射来获取关联实体的类型l

15、not-found属性:指定当从表记录参照的主表记录不存在时,Hibernate如何处理这种情况。“exception”或“ignore”9.1.3 单向单向1-N关联关联lPerson.javapublic class Person/标识属性private Integer id;/Person的name属性private String name;/保留Person的age属性private int age;/1N关联关系,使用Set来保存关联实体private Set addresses= new HashSet();/每个属性的 set方法和get方法,权限为publicAddress类无

16、需访问Person对象,所以程序无需任何改变9.1.3 单向单向1-N关联关联无连接表的单向无连接表的单向1-N在1的一端增加对应的集合映射元素,如、等元素为集合元素增加子元素,用以映射外键列使用9.1.3 单向单向1-N关联关联Person.hbm.xml使用没有指定cascade属性,在默认情况下,对主表实体的持久化操作不会级联到从表实体9.1.3 单向单向1-N关联关联PersonManager.java(片段片段)private void testPerson()Session session = HibernateUtil.currentSession();Transaction t

17、x = session.beginTransaction();/创建一个Person对象Person p = new Person();/创建一个瞬态的Address对象Address a = new Address(“Guangzhou);/必须先持久化Address对象session.persist(a); /设置Person的Name为Yeeku字符串p.setName(Yeeku); p.setAge(29);/设置Person和Address之间的关联关系p.getAddresses().add(a);/持久化Person对象session.save(p);/创建一个瞬态的Addre

18、ss对象Address a2 = new Address(“Shanghai);/先持久化Address对象session.persist(a2); /修改持久化状态的Person对象p.getAddresses().add(a2); mit(); HibernateUtil.closeSession();9.1.3 单向单向1-N关联关联l 程序性能分析l处持久化一个Person实体,增加一个关联Address实体l一条insert语句向person_inf表插入一条记录lHibernate会采用两条语句来完成关联一条insert语句插入一条外键为null的address_inf记录一条up

19、date语句来修改刚插入的address记录l问题:造成系统性能不好l原因l从Person到Address的关联没有被当做Address对象状态的一部分,Address对象并不知道它所关联的Person实体l解决办法l通过address.setPerson(person)方法来建立关联关系,l即把这个关联关系添加到Address的映射中,这就变成1-N双向关联9.1.3 单向单向1-N关联关联l有连接表的1-N关联映射,l映射文件不再使用元素映射关联实体,而是使用,l为了保证当前实体是1的一端,因此要为其指定unique=“true”lclass属性:指定关联实体的类名Person.hbm.x

20、mlHibernate: insert into address_inf (addressDetail) values (?)Hibernate: insert into person_inf (name, age) values (?, ?)Hibernate: insert into address_inf (addressDetail) values (?)Hibernate: insert into person_address (person_id, address_id) values (?, ?)Hibernate: insert into person_address (per

21、son_id, address_id) values (?, ?)Hibernate控制台显示信息:控制台显示信息:9.1.4 单向单向N-N关联关联l单向的N-N关联和1-N关联的持久化类代码完全相同,控制关系的一端需要增加一个Set类型的属性,被关联的持久化实例以集合形式存在。lN-N关联必须使用连接表l类似于有连接表的单向1-N关联。Person.hbm.xml9.2.1 双向N-1关联l两端都需要增加对关联属性的访问,N的一端增加引用到关联实体的属性,1的一端增加集合属性,集合元素为关联实体lPerson类作为1的一端,Address类作为N的一端l(bidirectional1-Nn

22、ojointable)无连接表l Person.javal Address.javal Person.hbm.xmll Address.hbm.xmlPerson.hbm.xmlAddress.hbm.xmlprivate void testPerson()Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();/创建一个Person对象Person p = new Person();/创建一个瞬态的Address对象Address a = new Address(

23、Guangzhou);/必须先持久化Address对象session.persist(a); /设置Person的Name为Yeeku字符串p.setName(Yeeku);p.setAge(29);/设置Person和Address之间的关联关系p.getAddresses().add(a);/持久化Person对象session.save(p);/创建一个瞬态的Address对象Address a2 = new Address(Shanghai);/先持久化Address对象session.persist(a2);/修改持久化状态的Person对象p.getAddresses().add(

24、a2);mit();HibernateUtil.closeSession();PersonManager类的部分代码保存一个Person对象,两个Address对象使用三条insert语句9.2.1 双向N-1关联(无连接表)l最好先持久化Person实体l当程序持久化Address实体时,Hibernate可以为Address的外键属性分配值l向address_inf插入记录时,该记录的外键列已指定了值,表明它参照的主表记录已存在。l先设置Person实体和Address实体的关系l否则,Hibernate在保存Address实体时,不能为对应记录的外键列指定值,等到设置关联关系时,Hibe

25、rnate只能再次使用update语句来修改关联关系。lPerson实体不控制关联关系lInverse=“true”9.2.2 双向N-N关联l双向N-Nl需要两端都采用Set集合属性,两端都增加对集合属性的访问。l只能用连接表来建立两个实体之间的关联关系lPerson.javal Address.javal Person.hbm.xmll Address.hbm.xmlPerson.hbm.xml(截取部分截取部分)Address.hbm.xml(截取部分截取部分) 两个两个元素的元素的table属性必须指定,而且要相同,属性必须指定,而且要相同,是同是同 一个连接表的表名,一个连接表的表名

26、, 元素的两个子元素元素的两个子元素 和和都必须指定都必须指定column属性属性 指定本持久化类在连接表中的外键列名指定本持久化类在连接表中的外键列名 指定关联类在连接表中的外键列名指定关联类在连接表中的外键列名 两个持久化类的两个持久化类的和和的的column属性交叉相同属性交叉相同9.2.3 双向双向1-1关联关联l基于外键的双向1-1关联l基于主键的双向1-1关联l有连接表的双向1-1关联9.3 数据查询方式l使用JDBC进行数据检索时,必须手动编写SQL语句,当在多个表之间进行级联查询时,有时还需要编写大量复杂的SQL语句,这些SQL语句在一定程度上降低了程序的可维护性。lHiber

27、nate提供的面向对象查询方式,通过正确配置关联关系,指定查询条件,就可以轻松得到数据,避免冗长的SQL代码。lHibernate支持的数据查询方式包括:HQL(Hibernate Query Language)QBC (Query by Criteria)原生SQL 9.3.1 数据查询方式HQLlHQL(Hibernate Query Language)lHibernate中最常用的面向对象查询语言lHQL的查询语句语法结构String hql=“from Customer as c”Query query=session.createQuery(hql);Customer:持久化类(非数

28、据表名称)c:持久化类中实例的别名9.3.1 数据查询方式HQLHQL(Hibernate Query Language)语法结构和SQL相似,其功能如下 :l支持条件查询。l支持连接查询。l支持分页查询。l支持动态绑定参数查询。l支持分组查询(having和group by)。l支持内置函数和自定义函数查询(sum()、min()、max())。l支持子查询,即嵌入式查询。9.3.1 数据查询方式HQLl支持属性查询lList list=session.createQuery(“select from Customer as c”).list( );l支持条件查询lList l

29、ist=session.createQuery(“select from Customer as c where is not null”).list( );l支持连接查询lList list=session.createQuery(“from Customer as c left join fetch c.orders”).list( );lleft join:左外连接,9.3.1 数据查询方式HQLl支持分页查询l当数据量很大时,采用分页查询可以使前台页面显得更美观Query query=session.createQuery(“from Customer as

30、 c order by c.id ”);/指定记录检索的开始位置/(结果集中的开始位置索引值默认为0)query.setFirstResult(5);/设置一次检索出来的最大记录数query.setMaxResult(15);List list=query.list();9.3.1 数据查询方式HQLl支持动态绑定参数查询l在HQL中使用条件查询时,有的查询需要输入指定的参数,此时可使用动态参数绑定查询。Query query=session.createQuery(“from Customer as c where =:cName”);Query.setString(“cName

31、”,“sunyang”);List list=query.list( );给参数赋值setString();setInteger()9.3.1 数据查询方式HQLl其他功能l分组查询l使用having和group by子句l内置函数和自定义函数查询lsum()、min()、max()等函数l子查询l在where条件语句中使用子查询9.3.1 数据查询方式HQLlSession类的find()方法以及Query接口都支持HQL检索方式。l前者只是执行一些简单HQL查询语句的便捷方法,不具有动态绑定参数的功能,而且在Hibernate3.x版本中,已经淘汰了find()方法;l而Query接口才是

32、真正的HQL查询接口,它提供了以上列出的各种查询功能。9.3.1 数据查询方式HQLHQL查询方式的实现步骤: /创建一个Query对象Query query=session.createQuery(from Customer as c where + =:customerName +and c.age=:customerAge);/动态绑定参数query.setString(customerName,Tom);query.setInteger(customerAge,21);/执行查询语句,返回查询结果List result= query.list();9.3.1 数据查询方式H

33、QL步骤:l创建Query对象l通过Session的createQuery()方法创建一个Query对象,l它包含一个HQL查询语句。lHQL查询语句可以包含命名参数,如“customerName”和“customerAge”都是命名参数。l动态绑定参数。lQuery接口提供了给各种类型的命名参数赋值的方法l例如setString()方法用于为字符串类型的customerName命名参数赋值。l调用Query的list()方法执行查询语句。l该方法返回List类型的查询结果,l在List集合中存放了符合查询条件的持久化对象。 9.3.2 数据查询方式QBClQBC(Query By Crite

34、ria)-条件查询l更具有面向对象特色的数据查询方式lCriteria是用来装载查询条件的容器(或者说将查询条件封装成一个Criteria对象,),Criteria容器会自动解析查询条件来进行数据检索,这种方式非常适合于动态查询。lQBC API l提供了检索对象的另一种方式l它主要由Criteria接口、Criterion接口和Expression类组成l它支持在运行时动态生成查询语句。l通过如下三个类完成lCriteria:代表一次查询lCriterion:代表一个查询条件lRestrictions:产生查询条件的工具类9.3.2 数据查询方式QBCQBC查询方式的实现步骤:/创建一个Criteria对象Criteria criteria=session.createCriteria(Customer.class);/设定查询条件,然后把查询条件加入到Criteria中Criterion criterion1= Expression.like(name, T%) ; Criterion criterion2= Expression.eq(age, new Integer(21) ;cri

温馨提示

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

评论

0/150

提交评论