实体与实体之间的多对一、一对多、一对一、多对多如何与Java对象之间进行映像

本文详细介绍了Java中的实体关系映射,包括多对一、一对多、一对一和多对多四种关系,并通过Hibernate映射文件展示了具体的实现方式。在多对一关系中,通过标签实现;一对多关系中,使用标签;一对一关系有两种方式,一种是通过外键,一种是通过主键关联。此外,文章还讨论了cascade的意义,以及在多对多关系中如何通过中介表完成映射。
摘要由CSDN通过智能技术生成

101多对一

一个实体简单的说就是在数据库中拥有一个表格,并拥有自已的数据库识别(Database identity)。

一个简单的实体与实体间之关系为多对一的关系,例如在学校宿舍中,使用者与房间的关系就是多对一的关系,多个使用者可以居住于一个房间。

如上图所示的,可以藉由room_id让使用者与房间产生关联,您可以如下建立userroom表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default '',

    room_id INT(11)

);

 

CREATE TABLE room (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    address VARCHAR(100) NOT NULL default ''

);

用程序来表示的话,首先看看User类别:

User.java

package onlyfun.caterpillar;

 

public class User {

    private Integer id;

    private String name;

    private Room room;

 

    public User() {

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public Room getRoom() {

        return room;

    }

 

    public void setRoom(Room room) {

        this.room = room;

    }  

}

User类别中有一room属性,将参考至Room实例,多个User实例可共同参考一个Room实例,Room类别设计如下:

Room.java

package onlyfun.caterpillar;

 

public class Room {

    private Integer id;

    private String address;

   

    public Room() {

    }

   

    public Integer getId() {

        return id;

    }

    public void setId(Integer id) {

        this.id = id;

    }   

   

    public String getAddress() {

        return address;

    }

   

    public void setAddress(String address) {

        this.address = address;

    }

}

在映射文件方面,先来看看Room.hbm.xml

Room.hbm.xml

<?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">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.Room" table="room">

        <id name="id" column="id">

            <generator class="native"/>

        </id>

 

        <property name="address"

                  column="address"

                  type="java.lang.String"/>

    </class>

 

</hibernate-mapping>

没什么,很简单的一个映射文件,而在User.hbm.xml中,使用<many-to-one>标签来映像多对一关系:

User.hbm.xml

<?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">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

 

        <property name="name" column="name" type="java.lang.String"/>

       

        <many-to-one name="room"

                     column="room_id"

                     class="onlyfun.caterpillar.Room"

                     cascade="all"

                     outer-join="true"/>        

    </class>

 

</hibernate-mapping>

<many-to-one>的设定中,cascade表示主控方(User)进行save-updatedelete相关操作时,被控方(Room)是否也一并进行相关操作,简单的说,也就是您储存或更新User实例时,当中的Room实例是否一并对数据库发生储存或操作,设定为 all,表示主控方任何操作,被控方也进行对应操作。

注意到room_id onlyfun.caterpillar.Room 对应 那么room_id的值为 Roomid

一个储存的例子如下:

Room room1 = new Room();

room1.setAddress("NTU-M8-419");

Room room2 = new Room();

room2.setAddress("NTU-G3-302");

       

User user1 = new User();

user1.setName("bush");

user1.setRoom(room1);

       

User user2 = new User();

user2.setName("caterpillar");

user2.setRoom(room1);

       

User user3 = new User();

user3.setName("momor");

user3.setRoom(room2);

 

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

       

session.save(user1); // 主控方操作,被控方也会对应操作

session.save(user2);

session.save(user3);

       

tx.commit();

session.close();

 

数据库中将储存以下的内容:

mysql> select * from user;

+-------+-------------+-----------+

| id    | name    | room_id |

+-------+-------------+-----------+

|  1   | bush     |      1 |

|  2   | caterpillar |      1 |

|  3   | momor   |      2 |

+-------+-------------+-----------+

3 rows in set (0.00 sec)

 

mysql> select * from room;

+----+-------------------+

| id | address        |

+----+-------------------+

|  1 | NTU-M8-419  |

|  2 | NTU-G3-302  |

+----+-------------------+

2 rows in set (0.00 sec)

 

在查询时的例子如下:

Session session = sessionFactory.openSession();

User user = (User) session.load(User.class, new Integer(1));

System.out.println(user.getName());

System.out.println(user.getRoom().getAddress());

session.close();

 

在设定outer-jointrue的情况下,Hibernate将使用以下的SQL一次查询所有的数据:

Hibernate:

select user0_.id as id1_, user0_.name as name0_1_, user0_.room_id as room3_0_1_,

room1_.id as id0_, room1_.address as address1_0_ from user user0_

left outer join room room1_ on user0_.room_id=room1_.id where user0_.id=?

在不设定outer-jointrue的情况下,Hibernate则使用以下的SQL分别查询userroom表格:

Hibernate:

select user0_.id as id0_, user0_.name as name0_0_, user0_.room_id as room3_0_0_

from user user0_ where user0_.id=?

Hibernate:

select room0_.id as id0_, room0_.address as address1_0_

from room room0_ where room0_.id=?

102 cascade 的意义

Java程序中,对象与对象之间会透过某些关系互相参考,如果有一个对象已经是持久化对象,被它参考的对象直觉上也应该要持久化,以维持对象之间关联的完整性,这是藉由可达性完成持久化(Persistence by reachability)的基本概念。

如果将对象之间的关联想象为一个树形图,从某一个持久化物件为树根出发,父节点若是持久化对象,则被父节点参考到的子节点应自动持久化,而另一方面,如果有一子节点没办法藉由任何的父节点来参考至它,则它没有被持久化的需求,它应从数据库中加以删除。<

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值