`
zisefeiniao
  • 浏览: 172434 次
  • 性别: Icon_minigender_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方式查询则不会起作用,还需要使用之前的方式处理延迟加载问题。




分享到:
评论

相关推荐

    hibernate关系映射

    以下是关于“Hibernate关系映射”的详细解释。 1. 一对一关系映射: Hibernate支持一对一(One-to-One)关系映射,这种关系通常存在于具有唯一性的关联表中。通过在实体类中使用`@OneToOne`注解,我们可以定义一对...

    hibernate关系映射多对多关系

    综上所述,这个压缩包提供了关于Hibernate关系映射的全面教程,包括多对多、一对一和一对多的关系配置,以及如何在Spring+Hibernate+Struts环境中应用这些关系。对于想要深入理解Hibernate并提升开发效率的Java...

    Hibernate对象关系映射

    Hibernate对象关系映射一对多 很基础等文档

    hibernate关系映射.doc

    hibernate关系映射,1V1,1vN,nVn,单相双相

    hibernate关系映射1to1及Nto1

    hibernate关系映射系列1,单向1对1映射,意向Nto1 程序说明:生成mysql数据库,建立DB Browser连接后,用户可在程序中自动生成mysql表,非常简单,适合初学者了解hibernate映射机制,有问题可联系flyallen5@hotmail.com

    Hibernate关系映射XML生成工具

    Hibernate是一款强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,而无需直接编写SQL语句。关系映射XML生成工具,如"Middlegen-Hibernate-r5",则是为了简化这一过程而设计的。这些工具能够自动...

    hibernate的关系映射

    **二、Hibernate关系映射的类型** 1. **一对一(OneToOne)**: 表示一个实体对应另一个实体的唯一实例。这可以通过在两个类中都定义`@OneToOne`注解来实现,并通过`mappedBy`属性指定被引用的一方。 2. **一对多...

    Hibernate_关联关系映射配置详解

    Hibernate_关联关系映射配置详解,希望能帮助广大java爱好者

    Hibernate的关联关系映射图解

    Hibernate4中映射关系图解。

    hibernate关系映射配置.rar

    &lt;hibernate-mapping&gt; &lt;class name="com.bjsxt.hibernate.User" table="t_user"&gt; &lt;!-- --&gt; &lt;/hibernate-mapping&gt; &lt;hibernate-mapping&gt; &lt;class name="com.bjsxt.hibernate.Group" ...

    hibernate关联映射详解

    hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的关联关系,...

    hibernate关系映射.chm

    现在我也正在学hibernate,于是我认为这东西对你也有用吧

Global site tag (gtag.js) - Google Analytics