一個實體簡單的說就是在資料庫中擁有一個表格,並擁有自已的資料庫識別(
Database identity
)。
一個簡單的實體與實體間之關係為多對一的關係,例如在學校宿舍中,使用者與房間的關係就是多對一的關係,多個使用者可以居住於一個房間。
如上圖所示的,可以藉由 room_id 讓使用者與房間產生關聯,您可以如下建立 user 與 room 表格:
一個簡單的實體與實體間之關係為多對一的關係,例如在學校宿舍中,使用者與房間的關係就是多對一的關係,多個使用者可以居住於一個房間。
如上圖所示的,可以藉由 room_id 讓使用者與房間產生關聯,您可以如下建立 user 與 room 表格:
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 ''
);
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;
}
}
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;
}
}
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>
<!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>
<!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-update 、 delete 等相關操作時,被控方( Room )是否也一併進行相關操作,簡單的說,也就是您儲存或更新 User 實例時,當中的 Room 實例是否一併對資料庫發生儲存或操作,設定為 all ,表示主控方任何操作,被控方也進行對應操作。
一個儲存的例子如下:
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();
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();
User user = (User) session.load(User.class, new Integer(1));
System.out.println(user.getName());
System.out.println(user.getRoom().getAddress());
session.close();
在設定 outer-join 為 true 的情況下, 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-join 為 true 的情況下, Hibernate 則使用以下的 SQL 分別查詢 user 與 room 表格:
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=?
Hibernate: select room0_.id as id0_, room0_.address as address1_0_ from room room0_ where room0_.id=?