当前位置:文档之家› Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结

Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结

Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结
Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结

Hibernate(6)——一对多和多对多关联关系映射(xml和注解)总结涉及的知识点总结如下:

?One to Many 映射关系

o多对一单向外键关联(XML/Annotation)

o一对多单向外键关联(XML/Annotation)

o懒加载和积极加载

o一对多双向外键关联(XML/Annotation)

?Many to Many 映射关系

o多对多单向外键关联(XML/Annotation)

o多对多双向外键关联(XML/Annotation)

o set的inverse元素详解

?问题小结

?关联关系的优缺点

多对一单向外键关联关系

注意多对一关联是多方持有一方的引用。看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示:

多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。对应数据库就是:

还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现:

基于注解的多对一单向外键关联:

单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name="cid"),而一方(教室类)无需做任何多方的定义。

注意;多方必须保留一个不带参数的构造器!

importjavax.persistence.Entity;

importjavax.persistence.GeneratedValue;

importjavax.persistence.Id;

//班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有

@Entity

public class ClassRoom {

private intcid;//班级编号

private String cname;//班级名称

// 自动增长的主键

@Id

@GeneratedValue

publicintgetCid() {

returncid;

}

public void setCid(intcid) {

this.cid = cid;

}

public String getCname() {

returncname;

}

public void setCname(String cname) {

https://www.doczj.com/doc/684082059.html,ame = cname;

}

}

View Code

一方——班级类无需做多余的定义,下面是多方——学生实体和配置:

importjavax.persistence.CascadeType;

importjavax.persistence.Entity;

importjavax.persistence.FetchType;

importjavax.persistence.GeneratedValue;

importjavax.persistence.Id;

importjavax.persistence.JoinColumn;

importjavax.persistence.ManyToOne;

//学生实体类,属于多对一的多方,持有班级(一方)的引用@Entity

public class Students {

private intsid; //编号

private String sname; //姓名

private ClassRoom classroom;//学生班级

//注意:多方一定要显式的定义不带参数的构造方法public Students() {

}

public Students(String sname)

{

this.sname = sname;

}

// 多方使用注解:@ManyToOne

// fetch=FetchType.EAGER,急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

// 全部级联操作,referencedColumnName显式设置数据库字段名cid,不写默认就是和name一样的。

@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER)

@JoinColumn(name="cid",referencedColumnName="cid") publicClassRoomgetClassroom() {

return classroom;

}

public void setClassroom(ClassRoom classroom) {

this.classroom = classroom;

}

// 自动增长主键

@Id

@GeneratedValue

publicintgetSid() {

returnsid;

}

public void setSid(intsid) {

this.sid = sid;

}

public String getSname() {

returnsname;

}

public void setSname(String sname) {

this.sname = sname;

}

}

View Code

下面测试:先生成数据库脚本,再进行学生对象的插入

public class TestStudentsByAnno {

private static SessionFactorysessionFactory;

@Before

public void setUp() throws Exception {

System.out.println("setUp()...");

sessionFactory = new

AnnotationConfiguration().configure().buildSessionFactory(); }

@After

public void tearDown() throws Exception {

System.out.println("tearDown()...");

sessionFactory.close();

}

@Test

public void testSave() {

Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction();

try {

ClassRoom c = new ClassRoom();

c.setCname("computer001");

Students s = new Students("zhangsan");

s.setClassroom(c);

session.save(s);

https://www.doczj.com/doc/684082059.html,mit();

} catch(Exception ex) {

ex.printStackTrace();

tx.rollback();

}

}

@Test

@Ignore

public void testSchemaExport() {

SchemaExport se = new SchemaExport(new

AnnotationConfiguration().configure());

se.create(true, true);

}

}

View Code

反向创建表的数据库脚本如下:

create table ClassRoom (cid integer not null auto_increment, cnamevarchar(255), primary key (cid))

create table Students (sid integer not null auto_increment, snamevarchar(255), cid integer, primary key (sid))

插入一个学生对象,会自动生成如下语句:

ClassRoom c = new ClassRoom();

c.setCname("computer001");

Students s = new Students("zhangsan");

s.setClassroom(c);

session.save(s);

https://www.doczj.com/doc/684082059.html,mit();

View Code

Hibernate: insert into ClassRoom (cname) values (?)

Hibernate: insert into Students (cid, sname) values (?, ?)

插入成功:

基于xml配置实现多对一单向外键关联

View Code

一方(教室类)无需做任何多方的定义。只需要维护好自己的属性配置即可。而多方只需要加上就ok。

View Code

hibernate.cfg.xml里加上

View Code

注意:如果没有设置级联ALL,那么需要在保存的时候先保存班级,在保存学生,否则出错: object references an unsaved transient instance - save the transient instance before flushing:

ClassRoomclassRoom = new ClassRoom();

classRoom.setCname("CS");

Students students = new Students("111");

students.setClassroom(classRoom);

session.save(classRoom);

session.save(students);

https://www.doczj.com/doc/684082059.html,mit();

View Code

小结:使用元素进行多对一关联关系配置,name属性指定类的属性名,column 属性指定库表字段名,class属性指定类属性类型(加上姓,即包名),not-null属性指定属性是否允许为空,cascade属性指定是否级联保存和更新:save-update、delete、all、none。

一对多单向外键关联

当类与类建立了关联,程序能很方便的从一个对象导航到另一个或一组与之关联的对象,有了student 对象,就可以通过student对象得到这个学生所属的班级的信息——students.getClassroom();,对于班级对象,如果想要得到某个学生的信息,怎么办呢?这时候可以反过来控制,一方控制多方,下面进行一对多单向外键关联。

简单说就是和之前多对一相反,之前是多方持有一方的引用,而一对多关联关系是一方持有多方的集合的引用,注意区别:这里是持有多方的集合。

基于注解的配置:

@OneToMany(cascade={CascadeType.ALL},fetch=https://www.doczj.com/doc/684082059.html,ZY),

@JoinColumn(name=""),除了级联之外,还要设置一方为懒加载模式。且外键还是加在了多方学生表里,只不过控制权变了,之前多对一关联是多方学生持有班级外键,控制班级,现在一对多关联,表里还是多方学生持有班级一方的外键,只不过控制权交给了班级,让班级控制学生。不要混淆。

importjavax.persistence.*;

importjava.util.Set;

//班级类是一方,一方持有多方的引用

@Entity

public class ClassRoom {

private intcid;//班级编号

private String cname;//班级名称

private Setstus ;//班级的学生集合是多方

// 现在是一方维护多方了,主控权交给了一方,设置级联,一方要设置懒加载,推荐!

@OneToMany(cascade={CascadeType.ALL},fetch=https://www.doczj.com/doc/684082059.html,ZY)

@JoinColumn(name="cid") // 设置一方的外键,这里是cid,因为实际上这个外键还是加在多方,只不过控制权变了。

public SetgetStus() {

returnstus;

}

public void setStus(Setstus) {

this.stus = stus;

}

@Id

@GeneratedValue

publicintgetCid() {

returncid;

}

public void setCid(intcid) {

this.cid = cid;

}

public String getCname() {

returncname;

}

public void setCname(String cname) {

https://www.doczj.com/doc/684082059.html,ame = cname;

}

}

View Code

注意,不论多对一还是一对多,多方都要显式保留无参构造器。

importjavax.persistence.Entity;

importjavax.persistence.GeneratedValue; importjavax.persistence.Id;

//学生实体类

@Entity

public class Students {

private intsid; //编号

private String sname; //姓名

//注意:一定要保留这个默认不带参数的构造方法public Students(){

}

public Students(String sname)

{

this.sname = sname;

}

@Id

@GeneratedValue

publicintgetSid() {

returnsid;

}

public void setSid(intsid) {

this.sid = sid;

}

public String getSname() {

returnsname;

}

public void setSname(String sname) {

this.sname = sname;

}

}

View Code

执行数据库脚本,发现一方(主控方)还是和之前多对一的表结构一样,多方也是如此。

create table ClassRoom (cid integer not null auto_increment, cnamevarchar(255), primary key (cid))

create table Students (sid integer not null auto_increment, snamevarchar(255), cid integer, primary key (sid))

执行测试,保存学生,因为现在关系是一方维护,控制多方。肯定保存主控方——班级(和之前相反,之前多对一保存的是多方学生对象),但是本质上还是先保存的学生班级,再自动保存学生,这点和多对

一本质一样。

Setstus = new HashSet<>();

stus.add(new Students("zhangsan"));

stus.add(new Students("lisi"));

stus.add(new Students("wangwu"));

stus.add(new Students("zhaoliu"));

stus.add(new Students("sunqi"));

ClassRoom c = new ClassRoom();

c.setCname("cs001");

c.setStus(stus);

session.save(c);

https://www.doczj.com/doc/684082059.html,mit();

View Code

生成的脚本如下:先插入外键的班级对象,在执行五个学生的插入操作,最后执行五个更新,为sid=1。。。5的学生,更新cid为2

Hibernate: insert into ClassRoom (cname) values (?)

Hibernate: insert into Students (sname) values (?)

Hibernate: insert into Students (sname) values (?)

Hibernate: insert into Students (sname) values (?)

Hibernate: insert into Students (sname) values (?)

Hibernate: insert into Students (sname) values (?)

Hibernate: update Students set cid=? wheresid=?

Hibernate: update Students set cid=? wheresid=?

Hibernate: update Students set cid=? wheresid=?

Hibernate: update Students set cid=? wheresid=?

Hibernate: update Students set cid=? wheresid=?

View Code

总结:多对一时候,多方设置EAGER,一方设置LAZY,也就是说,如果是多对一,多方控制一方,那么多方设置积极加载,一方无需多余配置,反过来,如果是一对多关系,一方控制多方,那么一方设置懒加载,多方无需多余配置,但是不论哪种,多方都显式加上一个不带参数的构造器。

一对多里的懒加载

记得之前总结,get和load的查询方式源码的时候,就总结了一下懒加载load里的应用,之前说Hibernate中,当访问的数据量过大时,用缓存也不太合适,因为内存容量有限,为了减少并发量,减少系统资源的消耗,Hibernate用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,比如之

前总结的load方式查询,当真正去使用对象的时候才会访问数据库。除了load查询默认使用懒加载,现在我们的一对多关联映射也使用了lazy加载,下面进行实际验证测试:

public void testQuery() {

Session session = sessionFactory.getCurrentSession();

Transaction tx = session.beginTransaction();

try {

// 首先查询班级,cid=1的班级

ClassRoom c =(ClassRoom) session.get(ClassRoom.class, 1);

// 通过班级导航到学生,遍历学生得到名字

for(Students s : c.getStus()) {

System.out.println("姓名 :" + s.getSname());

}

https://www.doczj.com/doc/684082059.html,mit();

} catch(Exception ex) {

ex.printStackTrace();

tx.rollback();

}

}

View Code

执行之后,debug发现:在没有使用班级对象的时候,只有这样一条SQL语句:从classroom表查询,cid=1的班级,使用使用AS赋给列一个别名。

Hibernate: select classroom0_.cid as cid0_0_, classroom0_.cname as cname0_0_ from ClassRoom classroom0_ where classroom0_.cid=?

View Code

等执行到for了,才打印这一语句:

Hibernate: select stus0_.cid as cid0_1_, stus0_.sid as sid1_, stus0_.sid as sid1_0_, stus0_.sname as sname1_0_ from Students stus0_ where

stus0_.cid=?

View Code

充分说明这是执行的懒加载模式。一方控制多方,一方设置懒加载,如果什么都不设置,会是什么情况?经过验证,发现和显式设置懒加载效果一样,也就是说,one-to-many(元素)的懒加载是默认的,这是必须的,是常用的策略。一对多的时候,查询主对象时默认是懒加载。即:查询主对象的时候不会把从对象查询出来,使用从对象的时候才加载从对象。

如果人为设置为积极加载,则直接全部查询,

@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER),SQL语句为如下,进行了外连接的查询。一次性查了主对象和从对象出来。

Hibernate: select classroom0_.cid as cid0_1_, classroom0_.cname as cname0_1_, stus1_.cid as cid0_3_, stus1_.sid as sid3_, stus1_.sid as sid1_0_, stus1_.sname as sname1_0_ from ClassRoom classroom0_ left outer join Students stus1_ on classroom0_.cid=stus1_.cid where

classroom0_.cid=?

View Code

基于xml文件配置:

一方作为主控方:

View Code

一方是班级,持有多方的集合,如下配置:

View Code

多方是学生,作为从对象,别忘了,保留无参构造器,如下配置:

View Code

一对多双向外键关联

其实类似之前的一对一双向外键关联,也是互相持有对方的引用,故也叫双向一对多自身关联。多方持有一方的引用,@ManyToOne(cascade={CascadeType.ALL}),@JoinColumn(name="")。反过来,一方也持有多方的集合,@OneToMany(cascade={CascadeType.ALL}),

@JoinColumn(name="")。代码如下:

基于注解的配置:

importjavax.persistence.CascadeType;

importjavax.persistence.Entity;

importjavax.persistence.FetchType;

importjavax.persistence.GeneratedValue;

importjavax.persistence.Id;

importjavax.persistence.JoinColumn;

importjavax.persistence.ManyToOne;

//学生实体类,属于多方,持有一方的引用

@Entity

public class Students {

private intsid; //编号

private String sname; //姓名

private ClassRoom classroom;//学生班级属于一方

//注意:一定要在多方保留这个默认不带参数的构造方法

public Students() {

}

public Students(String sname) {

this.sname = sname;

}

// 多方是设置积极加载,全部级联

@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER) @JoinColumn(name="cid",referencedColumnName="cid") // 外键设置为班级id,cid

publicClassRoomgetClassroom() {

return classroom;

}

public void setClassroom(ClassRoom classroom) {

this.classroom = classroom;

}

@Id

@GeneratedValue

publicintgetSid() {

returnsid;

}

public void setSid(intsid) {

this.sid = sid;

}

public String getSname() {

returnsname;

}

public void setSname(String sname) {

this.sname = sname;

}

}

View Code

关键是一方,也必须持有多方的集合,形成你中有我,我中有你的局面,互相控制。但是还是注意,本质上,数据库表里外键cid还是加在了学生表——多方的表里。

importjavax.persistence.*;

importjava.util.Set;

//班级类

@Entity

public class ClassRoom {

private intcid;//班级编号

private String cname;//班级名称

private Setstus; // 一方也持有了多方:学生的集合引用

// 一方也要控制多方,一方设置懒加载,外键还是cid,也就是外键还是加在多方——学生表。

@OneToMany(cascade={CascadeType.ALL},fetch=https://www.doczj.com/doc/684082059.html,ZY) @JoinColumn(name="cid")

public SetgetStus() {

returnstus;

}

public void setStus(Setstus) {

this.stus = stus;

}

@Id

@GeneratedValue

publicintgetCid() {

returncid;

}

public void setCid(intcid) {

this.cid = cid;

}

public String getCname() {

returncname;

}

public void setCname(String cname) {

https://www.doczj.com/doc/684082059.html,ame = cname;

}

}

View Code

测试脚本生成。和之前表一样,只不过控制权双方都有了:

alter table Students drop foreign key FK73AC29B8559B6D03 drop table if exists ClassRoom

drop table if exists Students

create table ClassRoom (cid integer not null auto_increment, cnamevarchar(255), primary key (cid))

create table Students (sid integer not null auto_increment, snamevarchar(255), cid integer, primary key (sid))

alter table Students add index FK73AC29B8559B6D03 (cid), add constraint FK73AC29B8559B6D03 foreign key (cid) references ClassRoom (cid)

View Code

此时先保存谁都可以!控制权是双方都有。

基于xml配置:

多方:,一方:记住,一方是持有集合

View Code

本例代码如下:

Hibernate配置文件的DTD

Hibernate中有两个配置文件 映射文件Xxx.hbm.xml 映射文件的的文件头DTD文件内容:

配置文件hibernate.cfg.xml 配置文件的文件头DTD文件内容: org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver jdbc:mysql://localhost/minmin?characterEncoding=gb2312 root minmin true create

Hibernate练习题

Hibernate&EJB考试试题 1、下面关于Hibernate说法正确的是()(选择两项) A)Hibernate是ORM的一种实现方式 B)Hibernate不要JDBC的支持 C)属于控制层 D)属于数据持久层 2、下面关于ORM的说法错误的是()(选择两项) A)对象关系映射,让现实中的对象同数据库的表产生映射(类与表产生映射) B)对象关系映射,让类同表产生关系 C)对象关系映射,让类同记录产生关系(类的实例与记录(表中的一行数据)产生关系) D)对象关系映射,让类中的属性同表中的列产生关系 3、下面关于Hibernate中Session的说法正确的是()(选择两项) A)Session是轻量级的,可以随意的创建和销毁 B)Session是重量级的,不能随意的创建和销毁 C)Session是线程安全的 D)Session不是线程安全的 4、在Hibernate中,以下()不属于session的方法 A、close() B. open() C. update() D. delete() 5、下面关于Hibernate中load和get方法说法正确的是() A)这两个方法是一样的,没有任何的区别 B)这两个方法不一样,load先找缓存,再找数据库

C)这两个方法不一样,get先找缓存,再找数据库 D)以上说法都不对 注:load()和get()都是先找缓存,再找数据库。 不同点是在检索时: load()是延迟检索,先返回代理对象,访问对象时在发出sql命令Get()是立即检索,直接发出sql命令,返回对象 6、在Hibernate中修改对象的说话错误的是() A)只能利用update方法来做修改 B)可以利用saveOrUpdate方法来做修改 C)可以利用HQL语句来做修改 D)不能利用HQL语句来修改 7、下面关于Hibernate中Transaction的使用说法正确的是()(选择两项) A)Transaction是可有可无的 B)Transaction在做查询的时候是可有可无的 C)Transaction在做修改的时候是可有可无的 D)Transaction在做修改的时候是必须的 8、使用Hibernate技术实现数据持久化时,下面()内容不在 Hibernate配置文件中配置(选择一项) A) 数据库连接信息 B) 数据库类型(dialect) C) show_sql参数 D) 数据库表和实体的映射信息

Hibernate3.6(开发必看)

1.Java对象持久化概述 1.1.应用程序的分层体系结构 1.1.1.基于B/S的典型三层架构 说明: 1,展现层:提供与用户交互的界面。 2,业务逻辑层:实现各种业务逻辑。 3,数据访问层:负责存放和管理应用程序的持久化业务数据。 1.1. 2.数据访问层与Hibernate在Java应用程序中的 角色 数据访问层(持久化层)封装了数据访问的细节,为业务逻辑层提供了面向对象的API。完善的持久化层应该达到的目标: 1,代码重用性高,可完成所有的数据访问操作。 2,如果需要的话,能够支持多种数据库平台。 3,具有相对独立性,当持久化层变化时,不会影响上层实现。 在数据访问层(持久化层)中可以使用Hibernate框架以实现要求,如下图所示:

1.2.软件模型 1.2.1.各种模型的说明 概念模型: 模拟问题域中的真实实体。描述每个实体的概念和属性及实体间关系。不描述实体行为。实体间的关系有一对一、一对多和多对多。。 关系数据模型: 在概念模型的基础上建立起来的,用于描述这些关系数据的静态结构。有以下内容组成:1,若干表 2,表的所有索引 3,视图 4,触发器 5,表与表之间的参照完整性

域模型: 在软件的分析阶段创建概念模型,在软件设计阶段创建域模型。 组成部分: 1,具有状态和行为的域对象。 2,域对象之间的关联。 域对象(domain object): 构成域模型的基本元素就是域对象。对真实世界的实体的软件抽象,也叫做业务对象(Business Object,BO)。域对象可代表业务领域中的人、地点、事物或概念。 域对象分为以下几种: 1,实体域对象:通常是指业务领域中的名词。(plain old java object,简单Java 对象)。 2,过程域对象:应用中的业务逻辑或流程。依赖于实体域对象,业务领域中的动词。如发出订单、登陆等。 3,事件域对象:应用中的一些事件(警告、异常)。 1.2.2.域对象间的关系 关联: 类间的引用关系。以属性定义的方式表现。

用MyEclipse如何自动生成hibernate的.hbm.xml文件

用MyEclipse如何自动生成hibernate的.hbm.xml文件(2010-07-29 17:36:01) 今天在网上看到很多人都不知道怎么用MyEclipse自动生成hibernate的.hbm.xml文件。我甚至看到有位兄弟竟然自己写出那个格式的文件来。首先我不得不佩服那位兄弟的记忆力。可是我这边有更直接的方法希望能对那些入门级别的人一点帮助! 在hibernate中,每个数据表对应的其实是一个实体类,每个实体类有一个对应的hbm.xml 配置文件和你匹配,myeclipse中其实有个MyEclipse Database Explorer视图,它提供了myeclipse与数据库直接连接的内置窗口,并且通过此窗口可以生成hibernate的mapping文件。 1.在项目上点击右键选择MyEclipse选项,为应用增加Hibernate特性. 2.在出现的配置窗口中,选中“Add Hibernate 2.1 libraries to project?”,然后设定存放Hibernate 库文件的目录为:/WEB-INF/lib 目录,默认会选择创建一个新的Hibernate配置文件hibernate.cfg.xml。 3.点击下一步,进入Hibernate数据库连接配置界面,在Connection Profile选项中直接选择在MyEclipse Database Explorer中配置的vipdata选项,然后就会自动生成其他的配置,可以选择“Copy JDBC Driver and add to classpath”,这样就会将JDBC驱动拷贝到WEB-INF/lib目录中。: 4.点击下一步,来创建Hibernate的SessionFactory类,这是一个简单的集中管理Hibernate 会话的工厂类,填写类的全名称。 5.点击完成,然后MyEclipse就会将Hibernate相关的jar包拷贝到lib目录下,同时会生成Hibernate的配置文件:hibernate.cfg.xml,和SessionFactory类。 现在要利用MyEclipse Database Explorer视图中的工具来生成Hibernate的映射文件。切换到MyEclipse Database Explorer视图,在表vipdata上点击右键,选择Create Hibernate Mapping.

Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结

Hibernate(6)——一对多和多对多关联关系映射(xml和注解)总结 涉及的知识点总结如下: ?One to Many 映射关系 o多对一单向外键关联(XML/Annotation) o一对多单向外键关联(XML/Annotation) o懒加载和积极加载 o一对多双向外键关联(XML/Annotation) ?Many to Many 映射关系 o多对多单向外键关联(XML/Annotation) o多对多双向外键关联(XML/Annotation) o set的inverse元素详解 ?问题小结 ?关联关系的优缺点 多对一单向外键关联关系 注意多对一关联是多方持有一方的引用。看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示: 多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。对应数据库就是: 还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现: 基于注解的多对一单向外键关联: 单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name="cid"),而一方(教室类)无需做任何多方的定义。 注意;多方必须保留一个不带参数的构造器! import ; import ; import ; //班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有

如何根据hibernate的实体类和实体类配置文件生成数据库的表

网络地址: 主题:如何根据hibernate的实体类和实体类配置文件生成数据库的表 内容部分 [c-sharp]view plaincopyprint? 1. 4. 5. 6. jdbc:mysql://12 7.0.0.1/lianxi 7. com.mysql.jdbc.Driver 8. root 9. root 10. org.hibernate.dialect.MySQLDialect 11. true 12. update 13. 14. 15. 16. 17. 18. 19.

hibernate关系映射注解配置

1. Hibernate Annotation关系映射有下面几种类型: 1)一对一外键关联映射(单向) 2)一对一外键关联映射(双向) 3)一对一主键关联映射(不重要,有需要看下文档即可) 在实际中很少用,使用注解@PrimaryKeyJoinColumn 意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试使用 注解一对一主键关联映射,在生成表的时候,数据库中并没有生成关联,使用XML 映射可以生成。Annotation注解一对一主键关联映,有些bug。不过没空去研究它。 因为在实际开发中一对一很少用。在实际开发中我机会没有用过,主键关联就更少了 4)多对一关联映射(单向) 5)一对多关联映射(单向) 6)一对多关联映射(双向) 7)多对多关联映射(单向) 8)多对多关联映射(双向) 2.介绍各种映射用法 1)一对一外键关联映射(单向)Husband ---> Wife public class Husband{ private Wife wife; @OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="wife_id",unique=true) public Wife getWife(){…} … } public class Wife{ } 一对一外键关联,使用@OneToOne,并设置了级联操作 @JoinColum设置了外键的名称为wife_id(数据库字段名),如果不设置,则默认为另一类的属性名+ _id 外键的值是唯一的(unique),不可重复,与另一类的主键一致 2)一对一外键关联映射(双向)Husband <---> Wife public class Husband{ private Wife wife; @OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="wife_id",unique=true) public Wife getWife(){…} ... } public class Wife{ private Husband husband; @OneToOne(mappedBy="wife",cascade=CascadeType.ALL) public Husband getHusband(){…} ... } 一对一双向关联关系,使用@OneToOne 注意:需要加上mappedBy="wife",如果不加上的话,Wife也会生成一个外键(husband_id)。mappedby="wife"需要指向与他关联对象的一个属性(即Husband类里面的wife属性),这里的会在Husband表里面生成个外键wife_id字段,而Wife表里则不会生成。这里Husband作为维护端即主

利用轻量对象关系映射技术Hibernate提高开发效率

利用轻量对象关系映射技术Hibernate提高开发效率 Enhancing Development Efficiency with Hibernate a Lightweight Object/Relational Mapping Technology 谢挺 周维民 (上海大学机电工程与自动化学院,上海 200072) 摘 要 Hibernate是一种轻量对象关系映射技术。文章通过实例,介绍了Hibernate的一些关键特性,并阐述了该技术的一些局限性。 关键词 Hibernate 对象关系映射企业级JavaBeans 持久化 Abstract Hibernate is a lightweight Object/Relational Mapping(ORM) technology. Some key features of Hibernate are illustrated, and some limits of this technology are expounded. Keywords Hibernate Object/Relational Mapping (ORM) EJB Permanence 0 引言 随着internet的发展,应用服务程序已经从集中式、C/S模式过渡到B/S、分布式模式;无论是用户或是供应商都迫切希望缩短开发周期、提高开发效率,Hibernate应运而生。 1 Hibernate简介 Hibernate是一个面向Java环境的对象/关系数据库映射工具。对象/关系数据库映射(Object/Relational Mapping , ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型中去。 Hibernate不仅提高Java类到数据库的映射,还提供数据查询和获取数据的方法。Hibernate在英语中的意思是“冬眠”,顾名思义它使得商务逻辑的开发和数据库最大程度地分离,可以大幅度减少开发时人工使用SQL和JDBC处理数据的时间。Hibernate的目标是解放开发者通常与数据持久化相关的编程任务的95%。对于那些在基于Java的中间层应用中,它们实现面向对象的业务模型和商业逻辑的应用,Hibernate是很有用的。 图1是Hibernate的体系结构图,从图中可以Array看到,系统为3层B/S模式,应用程序在客户端运 行将持久化的对象交由Hibernate。Hibernate通过 properties属性设置和XML Mapping实现商务逻 辑,调用和存储低层数据库后将返回的结果送给 客户端。 Hibernate对每一种数据库都有对应的 Dialect进行操作优化,从而提高它在各种情况 下的效率。目前,它的版本为3.0、支持的数据 库有Oracle、DB2、MySQL、PostgreSQL、Sybase,Interbase、Pointbase、Microsoft SQL Server、

Hibernate映射解决问题

Hibernate映射解决问题 做Hibernate映射已经做了五天了,期间遇到了不少错误,有的时候错误很细小,很难发现.现在就来总结一下,常见的错误,有的也是在网上搜了看到的! 第一种问题:Could not execute JDBC batch update 网上说有两种可能: 1.因为Hibernate Tools(或者Eclipse本身的Database Explorer)生成*.hbn.xml工具中包含有catalog="***"(*表示数据库名称)这样的属性,将该属性删除就可以了 2.估计是你的列名里面有关键字的原因吧,命名列的时候不要单独使用date,ID...这种关键字 但是,我觉得他写得不完全啦!我遇到的就不是两种原因,而是List映射时,对应表的索引项没有设成主键,所以就出错了.虽然找了蛮长时间的.同样, 它也会出现Duplicate entry '1' for key 1的错误啦! 第二种问题(归纳下): 1.Caused by: org.dom4j.DocumentException: Invalid byte 2 of 2-byte UTF-8 sequence. Nested exception: Invalid byte 2 of 2-byte UTF-8 sequence. 如果出现这行错误说明你的XML配置文件有不规范的字符,检查下。 2.net.sf.hibernate.MappingException: Error reading resource: hibernate/Hello_Bean.hbm.xml 如果出现这行错误说明你的hibernate的XML配置文件有错 3.net.sf.hibernate.MappingException: Resource: hibernate/Hello_Bean.hbm.xml not found 如果出现这行错误说明hibernate的XML配置文件没有找到,你应该把XML文件放在与你的类文件同个目录下,一般跟同名的java持久化类放在一起,也就是跟Hello_Bean.class类文件一起。4.net.sf.hibernate.PropertyNotFoundException: Could not find a setter for property name in class hibernate.Hello_Bean 如果出现这行错误说明你的xml文件里设置的字段名name的值与Hello_Bean.Java类里的getXXX 或setXXX方法不一致。 5.net.sf.hibernate.HibernateException: JDBC Driver class not found: org.gjt.mm.mysql.Driver:没有找到数据库驱动程序 6.The database return no natively generate indentity value。主键没有添加增量 7.net.sf.hibernate.PropertyValueException:not-null property references a null or transient value:com.pack.Rordercontent. 异常产生原因:Rordercontent对象的非空属性Rordertable引用了一个临时对象。 8.net.sf.hibernate.TransientobjectException:objiect references an unsaved transient instance –save the transient instance before flushing: com.pack.Rordertable 持久化对象的某个属性引用了一个临时对象Rordertable https://www.doczj.com/doc/684082059.html,.sf.hibernate.MappingException

Hibernate一对多映射

hibernate一对多关联映射—单向 一、简述 一对多关联映射(one-to-many) 1、在对象模型中,一对多的关联关系,使用集合表示 比如Classes(班级)和Student(学生)之间是一对多的关系 public class Classes{ private String id; private String name; private Set students; } public class Student{ public String id; public String name; } 2、我们以前学过学生对班级是多对一,返过来,班级对学生就是一对多。 3、我们多对一的关系是用户和组。返过来看,从组这边来看,就是一对多了。 下面学生的示例是班级和学生。和用户和组是一样的。 一个班级有多个学生,这是一对多的关系;返过来,多个学生属于一个班级,这就是多对一了。 4、建立对象模型 5、这两个对象模型之间是有关系的。我们现在讲的是一对多。一的一端是班级。多的一端是学生。那么怎么样能体现出这种关系呢? 我们在学习多对一时,是在多的一端加上一个字段。这个字段做为外键关联一的一端。多对一,就是我们在看到学生的时候,能够知道这个学生是哪个班级的。或者是当我们看到用户的时候,知道这个用户是哪个组的。所以在用户里面持有组的引用。 6、那么一对多,就是一个组里面有多少个用户。所以要维护这种关系,必须在组里面持有用户的集合。 班级和学生也是一样的。一个班级有多少学生,所以在班级里面要持有相应的学生的集合。如下图 我们用Set,通常用户Set做映射。

箭头表示两者之间是有关系的。 7、上面的是对象模型,那么这种模型要映射成什么样呢? 当我们定义多对一的关系时,在加载多的一端时,能够把1的一端加载上来。因为两者之间是有关系的。 同理,一对多也是一样的,它要维护这种关系。这种关系就是一对多。一的一端要指向多。在维护这种关系时,在加载一的时候,就会把一的一端加载上来。 也就是说,在我在加载班级时,这个班级有多少个学生,它会把所有的学生自动查询上来,放到Set集合里面。这就是维护这个关系的目的。 8、我们知道,实体类要映射成表。所在下面画两个表。 依我们来看,是先有班级。再分配学生。 学生有了,班级有了。要保证知道一个班级有多少学生。 因为students这个集合是在Classes上,要映射它的时候,那么我们是要在t_classes表上加一个字段,然后将所有的学生用,表达式表达出来吗?可是这样做不符合数据库的设计范式。 9、所以说,这种关系的维护应该是在t_student这一端。也就是说,在t_student表中加一个字段,这个字段就是classesid。 也就是说,一对多关联映射,要把两个表的关联字段加到多的一端。 10、所以说,一对多与多对一的映射是一样的。没有区别。都在多的一端加一个外键,指向一的一端。 但是两者也是有区别的。区别就是关系。如果维护的是多对一,则加载多的时候,能把1加上来。如果维护的是一对多,则加载班级时,能把WHSD1011对应的两个学生加载上来。 我的理解:对于要相关联的表来说,如果一个表想要看到对方的表内容,则就要在自己的实体类中持有对方的引用。 如果只有一方看到另一方,就是单向的。 如果要双方都看到,就要在实体模型中彼此都持有对方的引用。

hibernate映射文件property 元素属性

hibernate映射文件property 元素属性 property 元素 name:映射类属性的名字 可选属性: 1.column:对应数据库表的字段名默认值为属性名 2.type:字段的类型 3.update:update操作时是否包含本字段的数据默认值为true 4.insert:insert操作时是否包含本字段的数据默认值为true 5.formula:定义一个SQL来计算这个属性的值 6.access:Hibernate访问这个属性的策略默认值为property 7.unique:设置该字段值是否唯一默认值为false 8.not-null:设置该字段值是否可以为空默认值为false 9.property-ref:设置关联类的属性名,此属性和本类的关联相对应默认 值为关联类的主键 10.optimistic-lock:指定此属性做更新操作时是否需要乐观锁定默认值为 true https://www.doczj.com/doc/684082059.html,zy:指定是否采用延迟加载及加载策略默认值为proxy通过代理进行 关联可选值为 true此对象采用延迟加载并在变量第一次被访问时抓 取、false此关联对象不采用延迟加载 12.not-found:指定外键引用的数据不存在时如何让处理默认值为 exception产生异常可选值为ignore对不存在的应用关联到null 13.entity-name:被关联类的实体名 hibernate映射文件one-to-one 元素属性 1.one-to-one 元素 属性: https://www.doczj.com/doc/684082059.html,:映射类属性的名字 2.class:映射的目标类 3.cascade:设置操作中的级联策略可选值为 all所有操作情况均进行级 联、none所有操作情况均不进行级联、save-update执行更新操作时级联、delete执行删除操作时级联 4.constrained:表明当前类对应的表与被关联的表之间是否存在着外键约 束默认值为false

Hibernate 映射关联关系

Hibernate 映射关联关系 一、映射多对一关联关系。 1.单向的多对一 (1)以Customer 和Order 为例:一个用户可以发出多个订单,而一个订单只能属于一个客户。从Order 到Customer 是多对一关联关系。 (2)创建Customer 和Order 表。 Create (3)用Intellij Idea 自动生成关联关系,以及对应的Entitiy.hbm.xml 和持久化类。 说明: 其中Type 是用来修饰对应的Attribute Name 的。 在Order 端,定义Customer 类,一个订单属于一个客户。而在Customer 端,一个客户可以有多个订单,因为是单向的,所以这里放弃属性的添加。 在Join Columns 定义了Order 和Customer 之间的关联关系,order 表中的customer_id 外键和customer 表中的customer_id 主键关联。 来看生成的Schema: 没有勾选customer_id,是因为Intellij Idea 没法直接映射为Customer 类型的customer。 Order.hbm.xml 使用 节点来维护多对一关联关系。 name 属性:多这一端关联的一那一端的属性的名称。 class 属性:关联的一端的属性的类型。 column 属性:一那一端在多的一端对应的数据表中的外键。可以任意命名,但需要和数据表中的字段对应。 (4)单向多对一的CRUD 以及需要注意的问题。 <1> 新增

①先保存一的一端Customer,后保存多的一端Order。 Save.java 打印SQL: Output 结论:发送了3条INSERT 语句。 ②先保存多的一端Order,再保存一的一端Customer。 Save2.java 打印SQL: Output2 结论:发送了3条INSERT 语句,2条UPDATE 语句。 总结:在单向多对一的关联关系下,先插入 1 的一端会减少SQL 语句的执行,性能更高。 <2>删除 先删除1的一端。 Delete.java 控制台打印: Cannot delete or update a parent row: a foreign key constraint fails (`hibernate`.`order`, CONSTRAINT `FK_m6q2ofkj1g5aobtb2p00ajpqg` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`)) 结论:在不设置级联关系的前提下,不能删除 1 的一端。 <3>更新 Update.java Output <4>查询 ①查询n 的一端,但是不使用查询出来关联的 1 的一端的对象。 @Test public void testMany2OneGet() { Order order = (Order) session.get(Order.class, 1); System.out.println(order.getCustomer().getClass().getName()); } 复制代码

Hibernate考试试卷

Hibernate考试试题(题库) 1、在Hibernate中,下列说法正确的有()。【选三项】 A.Hibernate是一个开放源代码的对象关系映射框架 B.Hibernate对JDBC进行了轻量级的对象封装 C.Hibernate可以大大减少操作数据库的工作量 D.Hibernate提供了数据查询机制,但没有提供恢复机制 2、关于Hibernate,下列说法错误的是()。 A.Hibernate是一个对象-关系映射工具 B.在MVC模式中,Hibernate属于控制层 C.Hibernate在JDBC的方式上进行封装,以简化JDBC方式繁琐的编码工作 D.在Hibernate中,可以通过xml格式的配置文件保存对象-关系的映射信息 3、在Hibernate中,下列关于SessionFactory说法正确的有()。【选两项】 A.它是线程安全的 B.它不是线程安全的 C.它是轻量级的 D.一个SessionFactory实例对应一个数据存储源 4、在Hibernate中,下列关于Session说法正确的有()。【选三项】 A.它是线程安全的 B.它不是线程安全的 C.它是轻量级的 D.Session也被称为持久化管理器,它提供了和持久化相关的操作 5、在Hibernate中,下列关于Transaction说法正确的有()。【选三项】 A.事务Transaction为应用程序指定以原子操作单元为范围的对象 B.在对数据库进行增加、修改和删除操作时一定要加上Transaction C.在对数据库进行查询操作时一定要加上Transaction D.获得Transaction的方法:Transactiontr=session.beginTransaction(); 6、在Hibernate中,如果数据库是MySql或者SQLServer,则generator属性值不可 以使用()。 A.hilo B.native C.sequence D.indentity 7、在Hibernate中,如果数据库是Oracle或者DB2,则generator属性值不可以使用 ()。 A.hilo B.native C.sequence D.indentity 8、在Hibernate中,下列哪个选项不属于Session的方法()。 A.load B.save C.open

hibernate映射关系学习笔记

对象关联关系 一对一 单向:一方引用,在引用方加入被引用对象字段,注解@OneToOne 默认引用外键字段名为“被引用类名_id”,使用@JoinColumn(name=”your_name”)更改外键字段名 联合主键: @JoinColumns({ @JoinColumn(name="add_id",referencedColumnName="id"), @JoinColumn(name="add_code",referencedColumnName="areaCode") }) 双向:双方各自引用,都加入对方的引用,注解@OneToOne,表之间各自外键引用,不符合设计要求,通常一方引用,所以在被引用方法注解: @OneToOne(MappedBy=”引用方字段名”)。双向一般都设MappedBy 组件映射:一对一关系通常处理为在同一张表中存储数据,若程序端需要拆分成多个实体,使用组件映射方式@Embeded(在包含实体中注解) 若需要属性重写(改列名): @AttributeOverrides({ @AttributeOverride(name="fname",column=@Column(name="firstname")), @AttributeOverride(name="lname",column=@Column(name="lastname")) }) 多对一和一对多 多对一单向:在多方有一方的引用,注解@ManyToOne 一对多单向:在一的一方存在多方的集合(set),在一方注解@OneToMany 注意,Hibernate将一对多处理为多对多的特例,默认为两个关系表建中间表关联,所以加@JoinColumn 双向:多方注解@ManyToOne,一方注解@OneToMany(mappedBy="st")(st为多方引用一方对象名),注意一方不需再注解@JoinColumn 多对多 单向:在其中一方引用另外一方,类型为集合(set),注解@ManyToMany,若要改变中间表的表名及列名, 注解@JoinTable(name,joinColumns={@JoinColumn(name=”table1_id”)}, reverseJoinColumns={@JoinColumn(name=””)}) 双向:

在ECLIPSE中用HIBERNATE工具生成映射文件

总结的:在ECLIPSE中用HIBERNATE工具生成映射文件有截图 我们都知道HIBERNATE提供了工具供我们在ECLIPSE中使用生成对应的映射文件,但我一直用的都是myeclipse,兼容了需要导入的包,所以我对eclipse操作根本不熟,现在我在网上找了个案例,以后就不会头痛过了,(*^__^*) 嘻嘻…… 1.首先当然是从HIBERNATE官网上把工具下下来,放在ECLIPSE的对应的插件目录下 2.新建一个项目 3.把相应的JAR包加到你项目里 4.右击项目-〉new->Hibernate 选择Hibernate Configuration File(cfg.xml) 创建hibernate.cfg.xml文 件 5.(5)填写对应的数据库连接信息 如:Database dialet, connection URL, Default Schema, username, password等 记着:把下面那个Create a console configuration前面的钩钩上,下面会用它来创建映设文件 (6)点击NEXT,给你的Console Configuration 命个名,如test (7)FINISH你的hibernate.cfg.xml文件就建好了 下面是利用你的配置文件生成对应的映射JAVA文件 (8)进入hibernate Code Generation控制台,在Console configuration里选中你刚建的Console Configuration,如test (9)然后创建hibernate.reveng.xml 文件,选择新建 点击Refresh按钮,你的DB中的TABLE会列出来,然后将你要映射的表用INCLUDE按钮包含到右边的TABLE FILTERS中,点击FINISH (10)如下图,看看你要生成那些代码,把对应的钩打上,Apply-> Run ,OK,你对应的JAVA代码生成好了 注意:在我做以上步骤时曾发生过一下错误,重视下:

Hibernate之one-to-one主键关联映射

Hibernate之one-to-one主键关联映射one-to-one映射的例子为一个人拥有一个身份证,一个身份证属于一个人。 先创建po类 Person.java 1.package po; 2. 3.public class Person { 4.private int id; 5.private String name; //姓名 6.public int getId() { 7.return id; 8. } 9.public void setId(int id) { 10. this.id = id; 11. } 12. public String getName() { 13. return name; 14. } 15. public void setName(String name) { 16. https://www.doczj.com/doc/684082059.html, = name; 17. } 18. 19.} Card.java

1.package po; 2. 3.public class Card { 4.private int id; //身份证ID 5.private String number; //身份证号码 6.private Person person; //一个身份证号对应一个人 7. 8.public int getId() { 9.return id; 10. } 11. public void setId(int id) { 12. this.id = id; 13. } 14. public String getNumber() { 15. return number; 16. } 17. public void setNumber(String number) { 18. this.number = number; 19. } 20. public Person getPerson() { 21. return person; 22. } 23. public void setPerson(Person person) { 24. this.person = person; 25. } 26. 27. 28. 29. 30.}

Hibernate一对一映射配置详解

Hibernate一对一映射配置详解 雪飘寒 目录 Hibernate一对一映射配置详解 (1) 一、xml文件配置 (2) 1. 主键关联 (3) 2. 单方外键关联 (4) 3. 双方外键关联 (5) 二、注释方式配置(Annotation) (6) 1、主键关联 (6) 2. 单方外键关联 (7) 3. 双方外键关联 (8)

一对一关联分为主键关联与外键关联。 主键关联:不必加额外的字段,只是主表和辅表的主键相关联,即这两个主键的值是一样的。 外键关联:辅表有一个额外的字段和主表相关联,或者两个表都有额外的字段与对应表的相关联。一、xml文件配置 官方文档解释 (1) name: 属性的名字。 (2) class (可选 - 默认是通过反射得到的属性类型):被关联的类的名字。 (3) cascade(级联) (可选):表明操作是否从父对象级联到被关联的对象。 (4) constrained(约束) (可选):表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响save()和delete()在级联执行时的先后顺序以及决定该关联能否被委托(也在schema export tool中被使用). (5) fetch (可选 - 默认设置为选择): 在外连接抓取或者序列选择抓取选择其一. (6) property-ref (可选):指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键。 (7) access (可选 - 默认是 property): Hibernate用来访问属性的策略。 (8) formula (可选):绝大多数一对一的关联都指向其实体的主键。在一些少见的情况中,你可能会指向其他的一个或多个字段,或者是一个表达式,这些情况下,你可以用一个SQL公式来表示。(可以在org.hibernate.test.onetooneformula找到例子) (9) lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。lazy="false"指定此关联总是被预先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate会采取预先抓取! (10) entity-name (可选): 被关联的类的实体名。

相关主题
文本预览
相关文档 最新文档