- 浏览: 172458 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
gwill_21:
dwr.xml找不到怎么办,难道要自己手写dwr.xml?痛苦 ...
DWR框架 —— 用户注册验证 -
recoba7:
MLDN魔乐科技 Oracle学习笔记 (5) -
lanni2460:
呵呵 尽管现在才看到这个 但是我真的觉得 李老师 讲的很好呢 ...
严重声明,那些恶意诋毁MLDN及李兴华老师的其他培训机构统统走开 -
chian_xxp:
只要把功能实现了,代码结构合理了,代码性能提高了,该注意的注意 ...
业务、业务、业务。。。 -
wzpbb:
密码多少啊??? 给一下啊
MLDN 魔乐科技 Oracle 学习笔记(2)
Hibernate关系映射
三种映射关系:
1对1关系:一张表中的一条记录在另一张表中有且只有一条记录与其对应。(主外键,但包含外键的表其外键值也是主键)
1对多关系:一张表中的一条记录在另一张表中有多条记录与其对应,反过来只能找到一条记录对应。(主外键)
多对多关系:一张表中的一条记录在另一张表中有多条记录与其对应,反过来也可以找到多条记录。(三张表,其中有一个中间关系表,关系表为复合主键,并且包含另外两个表的主外键)
§3.1 Hibernate的1对1关系映射(1V1)
1、建立表
DROP TABLE card ;
DROP TABLE person ;
CREATE TABLE person (
id varchar(18) primary key ,
name varchar(20) not null,
age int not null
);
CREATE TABLE card(
id varchar(18) primary key ,
real_name varchar(20) not null,
birthday date not null,
city varchar(20) not null,
foreign key (id) references person (id) on delete cascade
) ;
2、生成映射
两个表同时生成Hibernate映射,不过在选择主键生成方式的那一步,先不要选,下一步的时候分别具体修改:
主键表选择assigned不变,而外键表选择foreign方式。
生成映射时,注意Card表的主键生成方式为foreign,表示其主键值依赖于外键关系,由person的主键值决定。
2、修改pojo类
MyEclipse在生成映射时,如果出现外键关系,默认按照一对多关系处理,如果要改为一对一,需要手工修改。
注意:在pojo中,对方对象的属性先不要实例化,否则有可能出现死循环。
package org.liky.pojo;
import java.util.Date;
/**
* Card generated by MyEclipse Persistence Tools
*/
public class Card implements java.io.Serializable {
// Fields
private String id;
private Person person;//不要实例化
private String realName;
private Date birthday;
private String city;
// Constructors
/** default constructor */
public Card() {
}
/** full constructor */
public Card(Person person, String realName, Date birthday, String city) {
this.person = person;
this.realName = realName;
this.birthday = birthday;
this.city = city;
}
// Property accessors
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public Person getPerson() {
return this.person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getRealName() {
return this.realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Date getBirthday() {
return this.birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
}
package org.liky.pojo;
/**
* Person generated by MyEclipse Persistence Tools
*/
public class Person implements java.io.Serializable {
// Fields
private String id;
private String name;
private Integer age;
private Card card;//不要实例化
// Constructors
/** default constructor */
public Person() {
}
/** minimal constructor */
public Person(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// Property accessors
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}
3、修改映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Person" table="person" catalog="testdb">
<id name="id" type="java.lang.String">
<column name="id" length="18" />
<generator class="assigned"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<!-- 表示在Person类中包含一个card属性 -->
<one-to-one name="card" class="org.liky.pojo.Card"></one-to-one>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Card" table="card" catalog="testdb">
<id name="id" type="java.lang.String">
<column name="id" length="18" />
<!-- 表示主键值由Card类中的person属性的主键值决定 -->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<one-to-one name="person" class="org.liky.pojo.Person" fetch="join"></one-to-one>
<property name="realName" type="java.lang.String">
<column name="real_name" length="20" not-null="true" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" not-null="true" />
</property>
<property name="city" type="java.lang.String">
<column name="city" length="20" not-null="true" />
</property>
</class>
</hibernate-mapping>
4、编写DAO
5、编写测试
(1)增加Card
(a)方法1
Card card = new Card();
// 需要先查询出该卡对应的人
try {
Person p = persondao.findById("123456789123456789");
card.setPerson(p);
p.setCard(card);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
card.setBirthday(new Date());
card.setRealName("Liky");
card.setCity("北京");
try {
carddao.doCreate(card);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意,卡的id是使用foreign方式,需要通过其person属性的id值来设置
(b)方法2
也可以不进行查询,而直接创建person对象,只需要将id值赋给person的id属性,并建立person与card 间的关系,就可以完成card的插入操作
Card card = new Card();
// 需要先查询出该卡对应的人
try {
Person p = new Person();
p.setId("123456789123456789");
card.setPerson(p);
p.setCard(card);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
card.setBirthday(new Date());
card.setRealName("Liky");
card.setCity("北京");
try {
carddao.doCreate(card);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(2)查询
try {
Person p = persondao.findById("123456789123456789");
System.out.println(p.getId()+" -- " +p.getName() + " -- " +p.getCard().getRealName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在查询时,发现查询person信息时,会自动查询出card的信息,查询方式使用join方式进行查询,该方式效率很低,可以通过修改映射文件中的fetch属性进行处理,默认为join,可以改为select方式
<!-- 表示在Person类中包含一个card属性 -->
<one-to-one name="card" class="org.liky.pojo.Card" fetch="select"></one-to-one>
(3)级联操作:cascade
级联操作在映射文件中通过cascade来进行设置,默认为none,表示不使用级联操作。
如果设置为all表示,调用session.save()、update()、delete()方法时,自动完成对关系表的操作(比如:一同插入,修改或删除),如果使用HQL方式,则此处cascade 不起作用(表中的on delete cascade配置与这里的配置无关,仍然起作用)。
级联所操作的是对方对象(本对象中的对方对象的属性)
Person person = new Person();
person.setId("987654321987654321");
person.setName("MLDN");
person.setAge(11);
Card c = new Card();
c.setRealName("NDLM");
c.setBirthday(new Date());
c.setCity("上海");
c.setPerson(person);
person.setCard(c);
try {
persondao.doCreate(person);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意修改时级联的内容,不能重新创建card对象,可以设置为null或使用原有内容
try {
Person p = persondao.findById("123456789123456789");
p.setName("abc");
p.setCard(new Card());//错误
persondao.doUpdate(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
§3.2 Hibernate 的1对多关系映射
一对多中:一的一方包含多的一方的一个对象集合(一般为Set),多的一方包含一的一方的一个对象。
组和人的关系:一个组中包含多个人,而一个人只属于一个组
1、建立表
DROP TABLE person ;
DROP TABLE groups ;
CREATE TABLE groups (
id int primary key auto_increment ,
title varchar(20) not null ,
description text not null
);
CREATE TABLE person (
uid varchar(18) primary key ,
name varchar(20) not null,
age int not null,
gid int not null,
foreign key (gid) references groups (id) on delete cascade
);
2、生成映射关系
两个表同时生成映射:
因为这里两个表的主键生成方式不同,所以单独配置两个表的主键生成方式
如果两个表的主键生成方式相同,在上一步的时候可以选择同样的主键生成方式即可。
2、查看pojo类
package org.liky.pojo;
/**
* Person generated by MyEclipse Persistence Tools
*/
public class Person implements java.io.Serializable {
// Fields
private String uid;
private Groups groups;
private String name;
private Integer age;
// Constructors
/** default constructor */
public Person() {
}
/** full constructor */
public Person(String uid, Groups groups, String name, Integer age) {
this.uid = uid;
this.groups = groups;
this.name = name;
this.age = age;
}
// Property accessors
public String getUid() {
return this.uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public Groups getGroups() {
return this.groups;
}
public void setGroups(Groups groups) {
this.groups = groups;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
package org.liky.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* Groups generated by MyEclipse Persistence Tools
*/
public class Groups implements java.io.Serializable {
// Fields
private Integer id;
private String title;
private String description;
private Set persons = new HashSet(0);
// Constructors
/** default constructor */
public Groups() {
}
/** minimal constructor */
public Groups(String title, String description) {
this.title = title;
this.description = description;
}
/** full constructor */
public Groups(String title, String description, Set persons) {
this.title = title;
this.description = description;
this.persons = persons;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Set getPersons() {
return this.persons;
}
public void setPersons(Set persons) {
this.persons = persons;
}
}
3、查看映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Groups" table="groups" catalog="testdb">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="title" type="java.lang.String">
<column name="title" length="20" not-null="true" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" not-null="true" />
</property>
<!-- 容器映射中配置过set集合,表示Groups类中包含一个Set集合类型的属性persons,inverse=true在这里表示关系由对方(person类)来控制 -->
<set name="persons" inverse="true">
<key>
<!-- 表示两个表之间的关系由person表中的gid来进行维护 -->
<column name="gid" not-null="true" />
</key>
<!-- 集合中保存的数据类型为Person类型,有一对多关系 -->
<one-to-many class="org.liky.pojo.Person" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Person" table="person" catalog="testdb">
<id name="uid" type="java.lang.String">
<column name="uid" length="18" />
<generator class="assigned"></generator>
</id>
<!-- 表示Person类中包含一个Groups类型的属性groups,与Person有多对一关系,查询方式使用select方式查询,而不是join方式 -->
<many-to-one name="groups" class="org.liky.pojo.Groups" fetch="select">
<!-- groups中的主键值对应person表中的gid的值 -->
<column name="gid" not-null="true" />
</many-to-one>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
</class>
</hibernate-mapping>
4、编写后台代码
5、编写测试类
(1)添加Group
在进行级联插入时,可以发现每次插入person之前先根据uid进行查询,判断该person是否存在,如果不存在,插入该person,如果存在,则修改该person的组
Groups group = new Groups();
group.setTitle("第四组");
group.setDescription("所有里面的第四组");
for (int i = 5; i < 15; i++) {
Person p = new Person();
p.setUid("uid"+i);
p.setName("name"+i);
p.setAge(i * i);
p.setGroups(group);
group.getPersons().add(p);
}
try {
groupdao.doCreate(group);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
执行效率不高,但代码很少。
(2)查询
查询时,注意延迟加载问题。
try {
Groups group = DAOFactory.getGroupDAOInstance().findById(3);
System.out.println(group.getTitle() + " --- " + group.getDescription());
System.out.println(group.getPersons());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(3)添加Person
Person person = new Person();
person.setUid("abc");
person.setName("Liky");
person.setAge(223);
person.setGroups(new Groups());
person.getGroups().setId(2);
try {
persondao.doCreate(person);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意其中组id的设置,需要通过groups属性的id值进行处理。
(4)通过person查询组信息
通过person查询组信息时,也会出现延迟加载问题,处理方式相同
try {
Person person = persondao.findById("abc");
System.out.println(person.getName() + " -- " + person.getAge());
System.out.println(person.getGroups().getTitle());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public Person findById(String id) throws Exception {
// TODO Auto-generated method stub
Person test = null;
try {
test = this.testdao.findById(id);
test.getGroups().getTitle();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return test;
}
注意在代理中通过getGroups取得groups后,需要调用getTitle等方法来使用该groups对象才能解决,而不能通过getId来使用,因为getId取得值不需要查询groups表,所以通过getId方式就仍然无法解决。
也可以通过修改映射文件中的查询方式处理该问题
<!-- 表示Person类中包含一个Groups类型的属性groups,与Person有多对一关系,查询方式使用select方式查询,而不是join方式 -->
<many-to-one name="groups" class="org.liky.pojo.Groups" fetch="join">
<!-- groups中的主键值对应person表中的gid的值 -->
<column name="gid" not-null="true" />
</many-to-one>
但这个设置会影响查询性能,而且该方式只能在session.get/load方法中使用,如果通过Query或Criteria方式查询则不会起作用,还需要使用之前的方式处理延迟加载问题。
三种映射关系:
1对1关系:一张表中的一条记录在另一张表中有且只有一条记录与其对应。(主外键,但包含外键的表其外键值也是主键)
1对多关系:一张表中的一条记录在另一张表中有多条记录与其对应,反过来只能找到一条记录对应。(主外键)
多对多关系:一张表中的一条记录在另一张表中有多条记录与其对应,反过来也可以找到多条记录。(三张表,其中有一个中间关系表,关系表为复合主键,并且包含另外两个表的主外键)
§3.1 Hibernate的1对1关系映射(1V1)
1、建立表
DROP TABLE card ;
DROP TABLE person ;
CREATE TABLE person (
id varchar(18) primary key ,
name varchar(20) not null,
age int not null
);
CREATE TABLE card(
id varchar(18) primary key ,
real_name varchar(20) not null,
birthday date not null,
city varchar(20) not null,
foreign key (id) references person (id) on delete cascade
) ;
2、生成映射
两个表同时生成Hibernate映射,不过在选择主键生成方式的那一步,先不要选,下一步的时候分别具体修改:
主键表选择assigned不变,而外键表选择foreign方式。
生成映射时,注意Card表的主键生成方式为foreign,表示其主键值依赖于外键关系,由person的主键值决定。
2、修改pojo类
MyEclipse在生成映射时,如果出现外键关系,默认按照一对多关系处理,如果要改为一对一,需要手工修改。
注意:在pojo中,对方对象的属性先不要实例化,否则有可能出现死循环。
package org.liky.pojo;
import java.util.Date;
/**
* Card generated by MyEclipse Persistence Tools
*/
public class Card implements java.io.Serializable {
// Fields
private String id;
private Person person;//不要实例化
private String realName;
private Date birthday;
private String city;
// Constructors
/** default constructor */
public Card() {
}
/** full constructor */
public Card(Person person, String realName, Date birthday, String city) {
this.person = person;
this.realName = realName;
this.birthday = birthday;
this.city = city;
}
// Property accessors
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public Person getPerson() {
return this.person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getRealName() {
return this.realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Date getBirthday() {
return this.birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
}
package org.liky.pojo;
/**
* Person generated by MyEclipse Persistence Tools
*/
public class Person implements java.io.Serializable {
// Fields
private String id;
private String name;
private Integer age;
private Card card;//不要实例化
// Constructors
/** default constructor */
public Person() {
}
/** minimal constructor */
public Person(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// Property accessors
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}
3、修改映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Person" table="person" catalog="testdb">
<id name="id" type="java.lang.String">
<column name="id" length="18" />
<generator class="assigned"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<!-- 表示在Person类中包含一个card属性 -->
<one-to-one name="card" class="org.liky.pojo.Card"></one-to-one>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Card" table="card" catalog="testdb">
<id name="id" type="java.lang.String">
<column name="id" length="18" />
<!-- 表示主键值由Card类中的person属性的主键值决定 -->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<one-to-one name="person" class="org.liky.pojo.Person" fetch="join"></one-to-one>
<property name="realName" type="java.lang.String">
<column name="real_name" length="20" not-null="true" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" not-null="true" />
</property>
<property name="city" type="java.lang.String">
<column name="city" length="20" not-null="true" />
</property>
</class>
</hibernate-mapping>
4、编写DAO
5、编写测试
(1)增加Card
(a)方法1
Card card = new Card();
// 需要先查询出该卡对应的人
try {
Person p = persondao.findById("123456789123456789");
card.setPerson(p);
p.setCard(card);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
card.setBirthday(new Date());
card.setRealName("Liky");
card.setCity("北京");
try {
carddao.doCreate(card);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意,卡的id是使用foreign方式,需要通过其person属性的id值来设置
(b)方法2
也可以不进行查询,而直接创建person对象,只需要将id值赋给person的id属性,并建立person与card 间的关系,就可以完成card的插入操作
Card card = new Card();
// 需要先查询出该卡对应的人
try {
Person p = new Person();
p.setId("123456789123456789");
card.setPerson(p);
p.setCard(card);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
card.setBirthday(new Date());
card.setRealName("Liky");
card.setCity("北京");
try {
carddao.doCreate(card);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(2)查询
try {
Person p = persondao.findById("123456789123456789");
System.out.println(p.getId()+" -- " +p.getName() + " -- " +p.getCard().getRealName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在查询时,发现查询person信息时,会自动查询出card的信息,查询方式使用join方式进行查询,该方式效率很低,可以通过修改映射文件中的fetch属性进行处理,默认为join,可以改为select方式
<!-- 表示在Person类中包含一个card属性 -->
<one-to-one name="card" class="org.liky.pojo.Card" fetch="select"></one-to-one>
(3)级联操作:cascade
级联操作在映射文件中通过cascade来进行设置,默认为none,表示不使用级联操作。
如果设置为all表示,调用session.save()、update()、delete()方法时,自动完成对关系表的操作(比如:一同插入,修改或删除),如果使用HQL方式,则此处cascade 不起作用(表中的on delete cascade配置与这里的配置无关,仍然起作用)。
级联所操作的是对方对象(本对象中的对方对象的属性)
Person person = new Person();
person.setId("987654321987654321");
person.setName("MLDN");
person.setAge(11);
Card c = new Card();
c.setRealName("NDLM");
c.setBirthday(new Date());
c.setCity("上海");
c.setPerson(person);
person.setCard(c);
try {
persondao.doCreate(person);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意修改时级联的内容,不能重新创建card对象,可以设置为null或使用原有内容
try {
Person p = persondao.findById("123456789123456789");
p.setName("abc");
p.setCard(new Card());//错误
persondao.doUpdate(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
§3.2 Hibernate 的1对多关系映射
一对多中:一的一方包含多的一方的一个对象集合(一般为Set),多的一方包含一的一方的一个对象。
组和人的关系:一个组中包含多个人,而一个人只属于一个组
1、建立表
DROP TABLE person ;
DROP TABLE groups ;
CREATE TABLE groups (
id int primary key auto_increment ,
title varchar(20) not null ,
description text not null
);
CREATE TABLE person (
uid varchar(18) primary key ,
name varchar(20) not null,
age int not null,
gid int not null,
foreign key (gid) references groups (id) on delete cascade
);
2、生成映射关系
两个表同时生成映射:
因为这里两个表的主键生成方式不同,所以单独配置两个表的主键生成方式
如果两个表的主键生成方式相同,在上一步的时候可以选择同样的主键生成方式即可。
2、查看pojo类
package org.liky.pojo;
/**
* Person generated by MyEclipse Persistence Tools
*/
public class Person implements java.io.Serializable {
// Fields
private String uid;
private Groups groups;
private String name;
private Integer age;
// Constructors
/** default constructor */
public Person() {
}
/** full constructor */
public Person(String uid, Groups groups, String name, Integer age) {
this.uid = uid;
this.groups = groups;
this.name = name;
this.age = age;
}
// Property accessors
public String getUid() {
return this.uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public Groups getGroups() {
return this.groups;
}
public void setGroups(Groups groups) {
this.groups = groups;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
package org.liky.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* Groups generated by MyEclipse Persistence Tools
*/
public class Groups implements java.io.Serializable {
// Fields
private Integer id;
private String title;
private String description;
private Set persons = new HashSet(0);
// Constructors
/** default constructor */
public Groups() {
}
/** minimal constructor */
public Groups(String title, String description) {
this.title = title;
this.description = description;
}
/** full constructor */
public Groups(String title, String description, Set persons) {
this.title = title;
this.description = description;
this.persons = persons;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Set getPersons() {
return this.persons;
}
public void setPersons(Set persons) {
this.persons = persons;
}
}
3、查看映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Groups" table="groups" catalog="testdb">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="title" type="java.lang.String">
<column name="title" length="20" not-null="true" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" not-null="true" />
</property>
<!-- 容器映射中配置过set集合,表示Groups类中包含一个Set集合类型的属性persons,inverse=true在这里表示关系由对方(person类)来控制 -->
<set name="persons" inverse="true">
<key>
<!-- 表示两个表之间的关系由person表中的gid来进行维护 -->
<column name="gid" not-null="true" />
</key>
<!-- 集合中保存的数据类型为Person类型,有一对多关系 -->
<one-to-many class="org.liky.pojo.Person" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.Person" table="person" catalog="testdb">
<id name="uid" type="java.lang.String">
<column name="uid" length="18" />
<generator class="assigned"></generator>
</id>
<!-- 表示Person类中包含一个Groups类型的属性groups,与Person有多对一关系,查询方式使用select方式查询,而不是join方式 -->
<many-to-one name="groups" class="org.liky.pojo.Groups" fetch="select">
<!-- groups中的主键值对应person表中的gid的值 -->
<column name="gid" not-null="true" />
</many-to-one>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
</class>
</hibernate-mapping>
4、编写后台代码
5、编写测试类
(1)添加Group
在进行级联插入时,可以发现每次插入person之前先根据uid进行查询,判断该person是否存在,如果不存在,插入该person,如果存在,则修改该person的组
Groups group = new Groups();
group.setTitle("第四组");
group.setDescription("所有里面的第四组");
for (int i = 5; i < 15; i++) {
Person p = new Person();
p.setUid("uid"+i);
p.setName("name"+i);
p.setAge(i * i);
p.setGroups(group);
group.getPersons().add(p);
}
try {
groupdao.doCreate(group);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
执行效率不高,但代码很少。
(2)查询
查询时,注意延迟加载问题。
try {
Groups group = DAOFactory.getGroupDAOInstance().findById(3);
System.out.println(group.getTitle() + " --- " + group.getDescription());
System.out.println(group.getPersons());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(3)添加Person
Person person = new Person();
person.setUid("abc");
person.setName("Liky");
person.setAge(223);
person.setGroups(new Groups());
person.getGroups().setId(2);
try {
persondao.doCreate(person);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意其中组id的设置,需要通过groups属性的id值进行处理。
(4)通过person查询组信息
通过person查询组信息时,也会出现延迟加载问题,处理方式相同
try {
Person person = persondao.findById("abc");
System.out.println(person.getName() + " -- " + person.getAge());
System.out.println(person.getGroups().getTitle());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public Person findById(String id) throws Exception {
// TODO Auto-generated method stub
Person test = null;
try {
test = this.testdao.findById(id);
test.getGroups().getTitle();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return test;
}
注意在代理中通过getGroups取得groups后,需要调用getTitle等方法来使用该groups对象才能解决,而不能通过getId来使用,因为getId取得值不需要查询groups表,所以通过getId方式就仍然无法解决。
也可以通过修改映射文件中的查询方式处理该问题
<!-- 表示Person类中包含一个Groups类型的属性groups,与Person有多对一关系,查询方式使用select方式查询,而不是join方式 -->
<many-to-one name="groups" class="org.liky.pojo.Groups" fetch="join">
<!-- groups中的主键值对应person表中的gid的值 -->
<column name="gid" not-null="true" />
</many-to-one>
但这个设置会影响查询性能,而且该方式只能在session.get/load方法中使用,如果通过Query或Criteria方式查询则不会起作用,还需要使用之前的方式处理延迟加载问题。
发表评论
-
本小姐回来啦 —— 超级感谢MLDN
2009-08-10 13:24 1600我又回来了!哈哈,报告一个好消息,我已经成功入职博彦科 ... -
现在开始积极的找工作
2009-07-05 19:13 1176学习差不多了,得赶在毕业前找到一个工作啊,本小姐这段时 ... -
素质教育 —— 模拟面试
2009-06-30 19:10 1045今天一天都安排了职业素质的培养,包括简历的指导、技术面 ... -
EJB实体Bean开发的复合主键映射
2009-06-29 21:36 1686复合主键的映射:在Hibernate中是通过一个主键类来完成复 ... -
EJB实体Bean开发
2009-06-29 21:33 990EJB实体Bean开发的数据库连接采用数据源连接池的方式,因此 ... -
EJB3.0
2009-06-28 14:14 1233EJB是SUN公司提出的开发 ... -
JBoss服务器配置
2009-06-25 21:21 2079哦,哦,哦,EJB的准备课程啊。 这里开发使用的是 JB ... -
Spring结合iBATIS进行开发
2009-06-25 21:19 963使用Spring管理iBATIS完全可以参照Spring+Hi ... -
ibatis开发框架
2009-06-25 21:17 1258iBATIS为一个ORMapping框架,可以帮助开发人员完成 ... -
WebService分布式开发
2009-06-24 22:23 1907WebService:用来跨语言传递数据。 数据交互是通过XM ... -
北京下雨了
2009-06-18 19:56 772上次在公交车上,听到电视里放《北京下雨了》,那么北京今天 ... -
JQuery
2009-06-10 21:03 12621、JQuery的基本语法 ... -
AJAX中使用JSON
2009-06-10 21:02 1303在Java开发中,如果要使用JSON进行开发,需要一些支持,这 ... -
AJAX框架 —— JSON基本知识
2009-06-10 21:01 944我真想知道这年头到底有多少种框架。 1、JSON ... -
还应该多帮助同学,才能让自己进步快
2009-06-08 21:57 990今天对于本小姐来讲还真是相对轻松的一天啊,上周完成了任 ... -
业务、业务、业务。。。
2009-06-03 18:41 1142项目就是业务,项目中都是业务,技术就这么点东西,只要把 ... -
IBM Project 继续中ing....
2009-06-02 19:08 874项目就是要坚持的做下去,而且要想到做到最好,虽然框架很好 ... -
实际开发了
2009-06-01 18:17 880今天开始新的项目了,项目老师帮我们搭建好了SVN服务器, ... -
web学习笔记 —— 数据源
2009-05-31 19:56 1025使用数据源可以提升数据库的操作性能,当然,不管使用与否,对于程 ... -
SSH(Spring + Struts + Hibernate)
2009-05-31 19:47 2490Spring结合Hibernate ...
相关推荐
以下是关于“Hibernate关系映射”的详细解释。 1. 一对一关系映射: Hibernate支持一对一(One-to-One)关系映射,这种关系通常存在于具有唯一性的关联表中。通过在实体类中使用`@OneToOne`注解,我们可以定义一对...
综上所述,这个压缩包提供了关于Hibernate关系映射的全面教程,包括多对多、一对一和一对多的关系配置,以及如何在Spring+Hibernate+Struts环境中应用这些关系。对于想要深入理解Hibernate并提升开发效率的Java...
Hibernate对象关系映射一对多 很基础等文档
hibernate关系映射,1V1,1vN,nVn,单相双相
hibernate关系映射系列1,单向1对1映射,意向Nto1 程序说明:生成mysql数据库,建立DB Browser连接后,用户可在程序中自动生成mysql表,非常简单,适合初学者了解hibernate映射机制,有问题可联系flyallen5@hotmail.com
Hibernate是一款强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,而无需直接编写SQL语句。关系映射XML生成工具,如"Middlegen-Hibernate-r5",则是为了简化这一过程而设计的。这些工具能够自动...
**二、Hibernate关系映射的类型** 1. **一对一(OneToOne)**: 表示一个实体对应另一个实体的唯一实例。这可以通过在两个类中都定义`@OneToOne`注解来实现,并通过`mappedBy`属性指定被引用的一方。 2. **一对多...
Hibernate_关联关系映射配置详解,希望能帮助广大java爱好者
Hibernate4中映射关系图解。
<hibernate-mapping> <class name="com.bjsxt.hibernate.User" table="t_user"> <!-- --> </hibernate-mapping> <hibernate-mapping> <class name="com.bjsxt.hibernate.Group" ...
hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的关联关系,...
现在我也正在学hibernate,于是我认为这东西对你也有用吧