第9章 Hibernate映射机制_第1页
第9章 Hibernate映射机制_第2页
第9章 Hibernate映射机制_第3页
第9章 Hibernate映射机制_第4页
第9章 Hibernate映射机制_第5页
已阅读5页,还剩67页未读 继续免费阅读

下载本文档

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

文档简介

1、9.1 主键映射主键映射9.2 数据类型映射数据类型映射9.3 对象关系映射对象关系映射9.4 动态类的使用动态类的使用1第一种区分方法第一种区分方法 单个主键:由表的单个字段组成。 复合主键:由表的多个字段共同组成。2第二种区分方法第二种区分方法 自然主键:具有业务意义的字段作为主键,例如,学生表中用XH(学号)作为主键。 代理主键:定义的、专门用来标识记录的id,它除了用来标识记录外,不具有任何的业务实体意义。但不管是什么主键,它都必须满足以下几个条件: 主键不能为空。 主键不能重复。 主键不能被修改。代理主键是自定义的、用来标识表记录的,不具有任何的业务实体意义,一般表中加入一个id字段

2、来标识。如【实例8.1】中POJO类表示为:public class UserTable implements java.io.Serializable / 属性private Integer id;/ 对应表中 id 字段/省略其他属性/构造方法/ 属性id的get和set方法public Integer getId() return this.id;public void setId(Integer id) this.id = id;/ 省略其他属性的get和set方法对应的映射文件配置为:下面列举这些生成方式,并简单介绍它们的应用方法。 assigned:应用程序自身对id赋值。 nat

3、ive:由数据库对id赋值。 hilo:通过hi/lo算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。 seqhilo:与hi/lo类似,通过hi/lo算法实现的主键生成机制,只是主键历史状态保存在sequence中,适用于支持sequence的数据库,如Oracle。 increment:主键按数值顺序递增。 identity:采用数据库提供的主键生成机制,如SQL Server、MySQL中的自增主键生成机制。 sequence:采用数据库提供的sequence机制生成主键,如Oracle sequence。 uuid.hex:由Hibernate基于128位唯一值产生算法

4、,根据当前设备IP、时间、JVM启动时间、内部自增量等4个参数生成十六进制数值(编码后长度为32位的字符串表示)作为主键。 uuid.string:与uuid.hex类似,只是对生成的主键进行编码(长度为16位)。在某些数据库中可能出现问题。 foreign:使用外部表的字段作为主键。该主键一般应用在表与表之间的关系上,会在后面的表对应关系上进一步讲解。 select:Hibernate 3引入的主键生成机制,主要针对遗留系统的改造工程。自然主键虽然不提倡使用,但使用自然主键的情况还是存在的,例如学生表,如果不单独指定代理主键id的话,就要用到自然主键XH(学号),POJO类编写为:publi

5、c class XS private String xh;public String getXh() return xh;public void setXh(String xh) this.xh = xh;/省略其他属性及get和set方法对应在映射文件中的主键配置为:1单独定义主键类单独定义主键类单独定义主键类,即把主键的属性组成一个新的类,这个类与要映射的POJO类类似,也要生成它的get和set方法,但是该类并不作为POJO类使用,而是作为映射POJO类的一个主键属性。假设有一个成绩表,该表的结构如表9.1所示。字 段 名数据类型主 键自 增允许为空描 述XHvarchar(50)是学号

6、KCHvarchar(50)是课程号CJint是成绩首先把主键封装成一个类,该类有两个要求。(1)实现java.lang.Serializable接口。(2)重写equals()和 hashCode()方法,当验证两个Cj对象是否相等时,Hibernate会使用这里的equals ()方法进行判断,即判断两个对象的xh和kch是否相等。然后在真正的映射POJO中使用:package org.vo;public class Cj implements java.io.Serializableprivate CjId id;private int cj;public CjId getId() re

7、turn id;public void setId(CjId id) this.id = id;public int getCj() return cj;public void setCj(int cj) this.cj = cj;POJO类编写完成后,可以编写配置文件Cj.hbm.xml,代码如下:配置完成后,下面来看复合主键如何操作数据库数据。 保存一个对象。public void saveCj()Transaction ts=session.beginTransaction();/定义事务CjId id=new CjId();/创建主键对象id.setXh(081101);/设置学号id

8、.setKch(001);/设置课程号Cj cj=new Cj();/创建POJO类对象cj.setId(id);/设置主键cj.setCj(80);/设置成绩session.save(cj);/保存mit();/提交事务 修改一个对象。public void updateCj()Transaction ts=session.beginTransaction();CjId id=new CjId();/创建主键对象id.setXh(081101);/设置学号id.setKch(001);/设置课程号Cj cj=(Cj) session.load(Cj.class, id);/根据主键得到对象c

9、j.setCj(90);/重新赋值成绩session.update(cj);/修改mit();/提交事务2不单独定义主键类不单独定义主键类不单独定义主键类,就是把主键属性直接放在POJO类中,不需要单独对其进行封装,那么该POJO类就要实现java.io.Serializable接口,并重写equals()和hashCode()方法。同样,映射文件Cj.hbm.xml也略有不同:由于这种情况是把主键放入POJO类中,故数据的存取也不同。 保存一个对象。public void saveCj()Transaction ts=session.beginTransaction(); /定义事务Cj c

10、j=new Cj(); /创建POJO类对象cj.setXh(081101); /设置学号cj.setKch(001); /设置课程号cj.setCj(80); /设置成绩session.save(cj); /保存mit(); /提交事务 修改一个对象。public void updateCj1()Transaction ts=session.beginTransaction();/根据学号及课程号查询,注意这里是HQL语句,Cj是类名,xh和kch是类中属性/关于HQL语言会在后面讲解Query query=session.createQuery(from Cj where xh=08110

11、1 and kch=001);Cj cj=(Cj) query.list().get(0); /得到第1个值cj.setCj(92);/重新赋值成绩session.update(cj);/修改mit();/提交事务在Hibernate的映射文件中,用标签来说明POJO类的属性与数据库表中的哪一个字段对应,用type属性说明对应属性应该使用什么数据类型。例如,【实例8.1】的UserTable. hbm.xml中有: 上面代码中的加黑部分,用type属性来指定数据类型,这个属性是Java数据类型,在Hibernate框架的内部还有一套“Hibernate数据类型”,Hibernate就是通过它将

12、Java类型自动转换为数据库标准的SQL类型,如图9.1所示,从而完成高质量的ORM映射。用户也可在配置文件中直接写入设置Hibernate自身的数据类型,代码如下:表9.2列举了各数据类型之间的对应关系。9.3.1 继承关系映射继承关系映射在实际应用中,存在这样一种情况:有很多种学生,如研究生、本科生等,它们都有学生的基本属性,但又有各自的特殊属性,故适合使用继承来实现这样的对象模型。例如,学生POJO类Xs.java代码为:public class Xs private int id;/id标识private String xh;/学号private String xm;/姓名privat

13、e Date bir;/出生时间/省略上述属性的get和set方法研究生POJO类Yjs.java代码为:public class Yjs extends Xsprivate String researchResult;/科研成果/省略属性get和set方法本科生POJO类Bks.java代码为:public class Bks extends Xsprivate boolean ky;/是否考研 /省略属性get和set方法可以看到,继承简化了程序的应用。现在就要考虑在数据库中建表的问题了,这种情况可以有3种方法来设计数据库。(1)每个子类一个数据表。(2)每个类一个数据表。(3)共享一个数

14、据表。1每个子类一个数据表每个子类一个数据表这种设计非常简单,并没有对这些继承关系的特性做任何处理,两张表对应了两个POJO类及各自的配置文件,它们之间并没有任何的关系。 设计两张数据库表,分别是yjs表(如表9.3所示)和bks表(如表9.4所示)。字 段 名数据类型主 键自 增允许为空描 述idint是增1id标识xhvarchar(50)学号xmvarchar(50)是姓名birdatetime是出生时间researchResultvarchar(50)是研究成果字 段 名数据类型主 键自 增允许为空描 述idint是增1id标识xhvarchar(50)学号xmvarchar(50)姓

15、名birdatetime出生时间kybit是否考研表9.3 yjs表表9.4 bks表 建立两张表对应的POJO类。Yjs.java代码为:package org.vo;import java.util.Date;public class Yjsprivate int id;/id标识private String xh;/学号private String xm;/姓名private Date bir;/出生时间private String researchResult;/科研成果/省略上述属性的get和set方法Bks.java代码为:package org.vo;import java.ut

16、il.Date;public class Bksprivate int id;/id标识private String xh;/学号private String xm;/姓名private Date bir;/出生时间private boolean ky;/是否考研/省略上述属性的get和set方法 建立POJO类对应的映射文件。Yjs.hbm.xml配置文件为:Bks.hbm.xml与Yjs.hbm.xml类似,只需要修改class的属性name和table的值,即把修改为:然后把研究生的特有属性修改为本科生特有的属性,即把改为:2每个类一个数据表每个类一个数据表【实例9.1】采用“每个类一个

17、数据表”的方式,实现继承关系映射。 创建Java项目,命名为“Inheritance_mapping”。 添加Hibernate框架,步骤同【实例8.1】第3步。HibernateSessionFactory类同样位于org.util包下。 在TEST数据库中创建表,设计xs表(如表9.5所示)、yjs表(如表9.6所示)、bks表(如表9.7所示)以及它们的关联关系。 在项目src下创建org.vo包,在其中建立POJO类。Xs.java代码为:public class Xs private Integer id;private String xh;private String xm;pri

18、vate Date bir;/省略上面属性的get和set方法Yjs.java代码为:public class Yjs extends Xsprivate Integer xsId;private String researchResult;/省略上面属性的get和set方法Bks.java代码为:public class Bks extends Xsprivate Integer xsId;private Boolean ky;/省略上面属性的get和set方法 配置Xs.hbm.xml。这种情况下只需要配置一个Xs.hbm.xml即可,在该配置文件中要把Yjs与Bks的信息配置出来。 对数

19、据的存取。/插入一条研究生记录public void saveYjs()Yjs yjs = new Yjs();yjs.setXh(081101);yjs.setXm(程明);yjs.setBir(new Date();yjs.setResearchResult(5项成果);Transaction ts = session.beginTransaction();session.save(yjs);mit();执行程序后,会把xh、xm、bir记录插入xs表中,把本条记录的id值及researchResult记录插入到yjs表中。/插入一条本科生记录public void saveBks()Bk

20、s bks = new Bks();bks.setXh(081102);bks.setXm(李方方);bks.setBir(new Date();bks.setKy(true);Transaction ts = session.beginTransaction();session.save(bks);mit();执行程序后,会把xh、xm、bir记录插入xs表中,把本条记录的id值及ky记录插入到bks表中。/查询记录public void query()List list = session.createQuery(from Yjs).list();for(int i=0;i);System

21、.out.println(yjs.getResearchResult();List list2 = session.createQuery(from Bks).list();for(int i=0;i);System.out.println(bks.getKy(); 编写测试类。在项目src下创建org.test包,其下建立测试类InheritanceTest.java,代码如下:public class InheritanceTest public Session session;public static void main(String args) InheritanceTest ht

22、= new InheritanceTest();/创建类对象ht.getCurrentSession();/获得session对象ht.saveYjs();/插入一条研究生记录ht.saveBks();/插入一条本科生记录ht.query();/查询记录ht.closeSession(); /关闭sessionpublic void getCurrentSession() /获得session方法public void closeSession() /关闭session方法public void saveYjs() /插入一条研究生记录public void saveBks() /插入一条本科

23、生记录public void query() /查询记录运行程序,测试结果如图9.2所示。3共享一个数据库表共享一个数据库表【实例实例9.2】采用“共享一个数据库表”的方式,实现继承关系映射。 采用这种方法,数据库中只要建立一张表即可,如表9.8所示。字 段 名数据类型主 键自 增允许为空描 述idint是增1id标识xhvarchar(50)学号xmvarchar(50)是姓名birdatetime是出生时间xsTypevarchar(50)是类型researchResultvarchar(50)是研究成果kybit是是否考研 POJO类的分配为,Xs.java中配置除子类各自独特属性外的所

24、有属性,子类只配置各自的独特属性。在项目src下建org.vo.one包,用于存放新编写的POJO类。Xs.java代码编写如下:public class Xs private int id;private String xh;private String xm;private Date bir;private String xsType;/省略上面属性的get和set方法Yjs.java代码编写如下:public class Yjs extends Xsprivate String researchResult;/省略get和set方法Bks.java代码编写如下:public class

25、Bks extends Xsprivate Boolean ky;/省略get和set方法该种情况也只需要配置一个映射文件Xs.hbm.xml即可,其子类信息及关系也会在映射文件中体现。 数据的存取也很简单,只需操作不同的类来得到想要得到的信息。/插入一条记录,并且该条记录为研究生public void saveYjs()Transaction t = session.beginTransaction();Yjs yjs = new Yjs();yjs.setXh(081103);yjs.setXm(jack);yjs.setBir(new Date();yjs.setResearchResu

26、lt(3项成果);session.save(yjs);mit();运行该段代码后,程序会根据Yjs类设置Xs表中的xsType值为“yjs”,并把值插入到Xs表中。/插入一条记录,并且该条记录为本科生public void saveBks()Transaction t = session.beginTransaction();Bks bks = new Bks();bks.setXh(081104);bks.setXm(jacy);bks.setBir(new Date();bks.setKy(true);session.save(bks);mit();运行该段代码后,程序会根据Bks类设置X

27、s表中的xsType值为“bks”,并把值插入到Xs表中。/查询记录public void query()List list = session.createQuery(from Xs where xsType=yjs).list();for(int i=0;i);System.out.println(yjs.getResearchResult();List list1 = session.createQuery(from Yjs).list();for(int i=0;i);System.out.println(yjs.getResearchResult();List list2 = ses

28、sion.createQuery(from Bks).list();for(int i=0;i);System.out.println(bks.getKy();运行程序,测试结果如图9.3所示。1一对一关联一对一关联 共享主键方式。在注册某个论坛会员的时候,往往不但要填写登录账号和密码,还要填写其他的详细信息,这两部分信息通常会放在不同的表中,如表9.9和表9.10所示。字段名称数据类型主 键自 增允许为空描 述IDint是id号USERNAMEvarchar(20)登录账号PASSWORDvarchar(20)登录密码字段名称数据类型主 键自 增允许为空描 述IDint是增1id号TRUEN

29、AMEvarchar(8)是真实姓名EMAILvarchar(50)是电子邮件表9.9 登录表login表9.10 详细信息表detail【实例9.3】共享主键方式示例。(1)创建Java项目,命名为“Hibernate_mapping”。(2)添加Hibernate框架,步骤同前。HibernateSessionFactory类同样位于org.util包下。(3)生成数据库表对应的Java类对象和映射文件。经过上面的操作,虽然MyEclipse自动生成了Login.java、Detail.java、Login.hbm.xml和Detail.hbm.xml共4个文件,但两表之间并未自动建立一对

30、一关联,仍需要用户修改代码和配置,手动建立表之间的关联。具体的修改内容如下,在源代码中以加黑标识。修改login表对应的POJO类Login.java,代码为。修改detail表对应的Detail.java,代码为:public class Detail implements java.io.Serializable private Integer id;/ id号private String truename;/ 真实姓名private String email;/ 电子邮件private Login login;/ 添加属性字段(登录信息)public Detail(String true

31、name, String email, Login login) this.truename = truename;this.email = email;this.login = login;/ 完善构造函数/ 增加 login 属性的 get 和 set 方法public Login getLogin()return this.login;public void setLogin(Login login)this.login = login;修改login表与Login类的ORM映射文件Login.hbm.xml为: detail 修改detail表与Detail类的ORM映射文件Detai

32、l.hbm.xml为: (4)创建测试类。在src下创建包test,在该包下建立测试类,命名为Test.java。其代码为。(5)运行程序,测试结果。因为该程序为Java Application,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,login表和detail表的内容如图9.4和图9.5所示。 唯一外键方式。对应的Person表和Room表如表9.11和表9.12所示。字段名称数据类型主 键自 增允许为空描 述idint是增1id号namevarchar(20)姓名room_idint是房间号字段名称数据类型主 键自 增允许为空描 述idint是

33、增1id号addressvarchar(100)地址表9.11 Person表表9.12 Room表【实例9.4】唯一外键方式示例。(1)在项目Hibernate_mapping的org.model包下生成表对应的POJO类对象和映射文件,然后按照如下的方法修改。修改Person表对应的POJO类Person.java,代码为。修改Room表对应的POJO类Room.java,代码为:public class Room implements java.io.Serializable private Integer id;/ id号private String address;/ 地址priva

34、te Person person;/ 增加 person 属性public Room(String address, Person person) this.address = address;this.person = person;/ 修改构造函数/ 增加 person 属性的 get 和 set 方法public Person getPerson()return this.person;public void setPerson(Person person)this.person = person;修改Person表与Person类的ORM映射文件Person.hbm.xml为: / 唯

35、一性约束,实现一对一 修改Room表与Room类的ORM映射文件Room.hbm.xml为: / 指定关联类的属性名 (2)编写测试代码。在src下的包test的Test类中加入如下代码:Person person=new Person();person.setName(liumin);Room room=new Room();room.setAddress(NJ-S1-328);person.setRoom(room);session.save(person);(3)运行程序,测试结果。因为该程序为Java Application,所以可以直接运行(运行时把前面的测试代码注释掉)。在完全没有

36、操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图9.6和图9.7所示。 2多对一单向关联多对一单向关联【实例9.5】多对一单向关联示例。(1)在【实例9.4】基础上修改,其对应表不变,表对应的Person类也不变,对应的Person. hbm.xml文件修改如下: / 主控类所有操作,对关联类也执行同样操作 而Room表不变,对应的POJO类修改如下:public class Room implements java.io.Serializable private Integer id;/ id号private String address;/ 地

37、址/private Person person;/ 删除 person 属性/* full constructor */public Room(String address) this.address = address;/this.person = person;/ 修改构造函数/ 省略上述各属性的get和set方法最后,在映射文件Room.hbm.xml中删去下面这一行:(2)编写测试代码。在src下包test的Test类中加入如下代码:Room room=new Room();room.setAddress(NJ-S1-328);Person person=new Person();pe

38、rson.setName(liuyanmin);person.setRoom(room);session.save(person);(3)运行程序,测试结果。直接运行Java Application程序,在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图9.8和图9.9所示。 3一对多双向关联一对多双向关联【实例9.6】一对多双向关联示例。(1)在【实例9.5】基础上修改,Person表对应的POJO及其映射文件不用改变,现在来修改Room表对应的POJO类及其映射文件。对应的POJO类Room.java如下:package org.mod

39、el;import java.util.*;/ 导入用于集合操作的 Jar 包public class Room implements java.io.Serializable private Integer id;/ id号private String address;/ 地址private Set person = new HashSet();/ 定义集合,存放多个 Person 对象/ 增加 Person 集合的get和set方法public Set getPerson()return person;public void setPerson(Set person)this.person

40、 = person;Room表与Room类的ORM映射文件Room.hbm.xml修改如下: /级联程度 /充当外键的字段名 /被关联的类名字 (2)编写测试代码。在src下的包test的Test类中加入如下代码:Person person1=new Person(); Person person2=new Person();Room room=new Room();room.setAddress(NJ-S1-328);person1.setName(李方方);person2.setName(王艳);person1.setRoom(room);person2.setRoom(room);/这样

41、完成后就可以通过Session对象调用session.save(person1)和session.save(person2),会自动保存roomsession.save(person1);session.save(person2);(3)运行程序,测试结果。因为该程序为Java Application,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图9.10和图9.11所示。 由于是双向的,当然也可以从Room的一方来保存Person,在Test.java中加入如下代码:.Person person1=new Perso

42、n(); Person person2=new Person();Room room=new Room();person1.setName(李方方);person2.setName(王艳);Set persons=new HashSet();persons.add(person1);persons.add(person2);room.setAddress(NJ-S1-328);room.setPerson(persons);/这样完成后,就可以通过Session对象调用session.save(room),会自动保存person1和person2.运行程序,插入数据后,Person表和Room

43、表的内容如图9.12和图9.13所示。 4多对多关联多对多关联 多对多单向关联。学生和课程就是多对多的关系,一个学生可以选择多门课程,而一门课程又可以被多个学生选择。多对多关系在关系数据库中不能直接实现,还必须依赖一张连接表,如表9.13、表9.14和表9.15所示。【实例9.7】单向多对多示例。(1)在项目Hibernate_mapping的org.model包下生成以上数据库表对应的POJO类对象和映射文件,然后进行修改。student表对应的POJO类修改如下:package org.model;import java.util.*;public class Student implem

44、ents java.io.Serializable private Integer id;/ ID号private String snumber;/ 学号private String sname;/ 姓名private Integer sage;/ 年龄private Set courses = new HashSet();/ 定义集合,存放多个 Course 对象/ 增加 Course 集合的get和set方法public Set getCourses()return courses;public void setCourses(Set courses)this.courses = cour

45、ses;student表与Student类的ORM映射文件Student.hbm.xml修改如下: / 级联程度 / 指定参照student表的外键名称 / 指定参照course表的外键名称 (2)编写测试代码。在src下的包test的Test类中加入如下代码:Course cour1=new Course();Course cour2=new Course();Course cour3=new Course();cour1.setCnumber(101);cour1.setCname(计算机基础);cour2.setCnumber(102);cour2.setCname(数据库原理);cou

46、r3.setCnumber(103);cour3.setCname(计算机原理);Set courses=new HashSet();courses.add(cour1);courses.add(cour2);courses.add(cour3);Student stu=new Student();stu.setSnumber(081101);stu.setSname(李方方);stu.setSage(21);stu.setCourses(courses);session.save(stu);/设置完成后就可以通过Session对象调用session.save(stu)完成持久化(3)运行程序

47、,测试结果。因为该程序为Java Application,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,student表、course表及连接表stu_cour的内容如图9.14、图9.15和图9.16所示。 多对多双向关联。【实例9.8】双向多对多示例。在【实例9.7】的基础上修改,首先将其course表所对应的POJO对象修改成如下代码:package org.model;import java.util.HashSet;import java.util.Set;public class Course implements java.io.Serializable private int id;/ ID号 private String cnumber;/ 课程号 private String cname;/ 课程名 private Set stus=new HashSet();/ 定义集合,存放多个 Student 对象 /省略上述各属性的get和set方法course表与Course类的ORM映射文件Course.hbm.xml改为: / 级联操作为所有 / 指定参照course表的外键名称 / 指定参照student表的外键名称 1配置映射文件配置映射文件例如,在讲解Hibern

温馨提示

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

评论

0/150

提交评论