Hibernate 学习笔记(3)

Hibernate的映射关联关系

1. 映射关联

多对一关联

一对一关联

一对多关联

双向一对多/多对一关联

多对多关联

2. 集合映射

<set>,<list>,<map>,<bag>,<array>,<primitive-array>

3. Component组件映射

4. Hibernate中的继承、多态结构的映射

Table per Class hierarchy 每个类分层结构一张表

Table per subclass 每个子类一张表

Table per concrete class 每个具体类一张表

映射策略之间的比较

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

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

如上图所示的,可以藉由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 ''
);

Hibernate的映射关联关系-多对一

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

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 

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 

<hibernate-mapping> 

    <class name=“com.cstp.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 

<hibernate-mapping> 

    <class name=“com.cstp.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=“com.cstp.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(“tiantian"); 
user1.setRoom(room1); 
        
User user2 = new User(); 
user2.setName(“hhp"); 
user2.setRoom(room1); 

User user3 = new User(); 
user3.setName(“zhangy"); 
user3.setRoom(room2); 

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
        
session.save(user1); // 主控方操作,被控方也会对应操作
session.save(user2);
session.save(user3);
        
tx.commit();
session.close();

怎么查询,例子如下:

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

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

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

Hibernate并没有完全实现以上的概念,它让使用者自行决定自动持久化的方式,当对象之间被指定关联(例如多对一、一对多等),您可以决定被持久化对象关联的暂存对象是否进行自动持久化与如何自动持久化。 在Hibernate中是以映像文件中卷标上的cascade(关联)属性来设定,预设为none,以 多对一 中的范例来说,如果不设定cascade为true,则您必须分别对User实例与Room实例进行储存:

Room room1 = new Room(); 
room1.setAddress("NTU-M8-419"); 
Room room2 = new Room(); 
room2.setAddress("NTU-G3-302"); 
        
User user1 = new User(); 
user1.setName(“tiantian"); 
user1.setRoom(room1);       
User user2 = new User(); 
user2.setName(“hhp"); 
user2.setRoom(room1);         
User user3 = new User(); 
user3.setName(“zhangy"); 
user3.setRoom(room2); 

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

// 储存Room实例
session.save(room1); 
session.save(room2);         
// 储存User实例
session.save(user1); 
session.save(user2);
session.save(user3);
        
tx.commit();
session.close();

使用cascade自动持久化时,会先检查被关联对象的id属性,未被持久化的对象是否储存是藉由id属性的unsaved-value决定,预设是 null,也就是没有参考至任何值时储存对象,如果您使用int、long这样的原生型态(Primitive type)时,由于数据成员的初始会被设定为0,所以您必须自行指定默认值,例如(如果id的数据类型是long的话):
....
        <id name="id" column="id" unsaved-value="0">
            <generator class="native"/> 
        </id> 
....

在 多对一 中,User对Room是多对一的关系,User实例维护着对Room实例的参考,如果将这个关系反过来,由Room实例维护对多个User实例的数据,就是一对多的关系。

具体来说,可以设计User类别如下: User.java 

public class User {
    private Integer id;
    private String name;
 
    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;
    }
}

而在Room类别中,使用Set来记录多个User:Room.java 

import java.util.Set;
public class Room { 
    private Integer id; 
    private String address;
    private Set users;
     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 Set getUsers() {
        return users;
    }
    public void setUsers(Set users) {
        this.users = users;
    } 
     public void addUser(User user) {
        users.add(user); 
    }
     public void removeUser(User user) {
        users.remove(user);
    }
}

这种方式即所谓单向一对多关系,也就是Room实例知道User实例的存在,而User实例则没有意识到Room实例。
(在 多对一 中,则是单向多对一关系,即User知道Room的存在,但Room不知道User的存在。)

在映射文件上,先来看看User.hbm.xml: 

User.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.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"/> 
 
    </class> 

</hibernate-mapping>

在单向关系中,被参考的对象其映射文件就如单一实体一样的配置,接下来看看Room.hbm.xml,使用<one-to- many>卷标配置一对多:

Room.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.Room" table="room"> 
        <id name="id" column="id"> 
            <generator class="native"/> 
        </id> 

        <property name="address" 
                  column="address" 
                  type="java.lang.String"/> 
 
        <set name="users" table="user" cascade="all">
            <key column="room_id"/>
            <one-to-many class=“com.cstp.User"/>
        </set>
    </class> 

</hibernate-mapping>

接着您可以如下储存对象:

User user1 = new User();
user1.setName(“tiantian"); 
        
User user2 = new User(); 
user2.setName(“hhp"); 
        
User user3 = new User(); 
user3.setName(“zhangy"); 

Room room1 = new Room(); 
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);

Room room2 = new Room();
room2.setUsers(new HashSet());
room2.setAddress("NTU-G3-302");
room2.addUser(user3);
        
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
        
session.save(room1);  // cascade 操作
session.save(room2); 
        
tx.commit();
session.close();

双向关联(inverse 的意义)

在 多对一 、一对多 中都是单向关联,也就是其中一方关联到另一方,而另一方不知道自己被关联。如果让双方都意识到另一方的存在,这就形成了双向关联,在多对一、一对多的例子可以改写一下,重新设计User类别如下: User.java 

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;
    }
}

Room类别如下:Room.java 

import java.util.Set;

public class Room { 
    private Integer id; 
    private String address;
    private Set users;
 
    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 Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    } 
 
    public void addUser(User user) {
        users.add(user); 
    }
 
    public void removeUser(User user) {
        users.remove(user);
    }
}

如此,User实例可参考至Room实例而维持多对一关系,而Room实例记得User实例而维持一对多关系。

在映射文件方面,可以如下编写: User.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.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=“com.cstp.Room"
                     cascade="save-update"
                     outer-join="true"/> 
    </class> 

</hibernate-mapping>

Room.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.Room" table="room"> 
        <id name="id" column="id"> 
            <generator class="native"/> 
        </id> 

        <property name="address" 
                  column="address" 
                  type="java.lang.String"/> 
 
        <set name="users" table="user" cascade="save-update">
            <key column="room_id"/>
            <one-to-many class=“com.cstp.User"/>
        </set>
    </class> 

</hibernate-mapping>

映像文件双方都设定了cascade为save-update,所以您可以用多对一的方式来维持关联:

User user1 = new User();
user1.setName(“tiantian"); 
        
User user2 = new User(); 
user2.setName(“hhp"); 

Room room1 = new Room(); 
room1.setAddress("NTU-M8-419");

user1.setRoom(room1);
user2.setRoom(room1);

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
        
session.save(user1);
session.save(user2);

tx.commit();
session.close();

或是反过来由一对多的方式来维持关联:

User user1 = new User();
user1.setName(“tiantian"); 
        
User user2 = new User(); 
user2.setName(“hhp"); 

Room room1 = new Room(); 
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
        
session.save(room1); 

tx.commit();
session.close();

这边有个效率议题可以探讨,上面的程序片段Hibernate将使用以下的SQL进行储存:

Hibernate: insert into room (address) values (?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: update user set room_id=? where id=?
Hibernate: update user set room_id=? where id=?

上面的程序写法表示关联由Room单方面维持,而主控方也是Room,User不知道Room的room_id是多少,所以必须分别储存Room与 User之后,再更新user的room_id。

在一对多、多对一形成双向关联的情况下,可以将关联维持的控制权交给多的一方,这样会比较有效率,理由不难理解,就像是在公司中,老板要记住多个员工的姓名快,还是每一个员工都记得老板的姓名快。

所以在一对多、多对一形成双向关联的情况下,可以在「一」的一方设定控制权反转,也就是当储存「一」的一方时,将关联维持的控制权交给「多」的一方,以上面的例子来说,可以设定Room.hbm.xml如下: Room.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.Room" table="room"> 
        <id name="id" column="id"> 
            <generator class="native"/> 
        </id> 

        <property name="address" 
                  column="address" 
                  type="java.lang.String"/> 
 
        <set name="users" table="user" cascade="save-update" inverse="true">
            <key column="room_id"/>
            <one-to-many class=“com.cstp.User"/>
        </set>
    </class> 

</hibernate-mapping>

由于关联的控制权交给「多」的一方了,所以直接储存「一」方前,「多」的一方必须意识到「一」的存在,所以程序片段必须改为如下:

User user1 = new User();
user1.setName(“tiantian"); 
        
User user2 = new User(); 
user2.setName(“hhp"); 

Room room1 = new Room(); 
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);

// 多方必须意识到单方的存在
user1.setRoom(room1);
user2.setRoom(room1);
        
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
        
session.save(room1); 

tx.commit();
session.close();

上面的程序片段Hibernate将使用以下的SQL:

Hibernate: insert into room (address) values (?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)


如果控制权交给另一方了,而另一方没有意识到对方的存在的话会如何?试着将上面的程序片段中user1.setRoom(room1);与 user2.setRoom(room1);移去,执行之后,您会发现数据库中room_id会出现null值,这种结果就好比在 多对一 中,您没有分配给User一个Room,理所当然的,room_id会出现null。

一对一(唯一外键关联)

现在考虑每一个User配给一间Room,形成一对一,user表格通过room_id作为外键参考至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 ''
);

对象方面,User的实例会参考至Room实例,而Room实例也参考至User实例:User.java 

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;
    }
}

Room.java 

public class Room { 
    private Integer id; 
    private String address;
    private User user;
 
    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 User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

使用外键来完成一对一,其实就是限制多对一关系中,「多」的一方只能有一个参考至「一」的一方,也就是多对一关系的一个特例,这可以在映像文件中使用 <many-to-one>标签时,加上"unique"属性来设定,例如:User.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.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=“com.cstp.Room"
                     cascade="all"
                     outer-join="true"
                     unique="true"/> 
    </class> 

</hibernate-mapping>

到这边为止,单向一对一的映像已经完成,如果要再完成双向一对一的关系,则可以在Room.hbm.xml中使用<one-to- one>标签来定义:

Room.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.Room" table="room"> 
        <id name="id" column="id"> 
            <generator class="native"/> 
        </id> 

        <property name="address" 
                  column="address" 
                  type="java.lang.String"/> 
 
        <one-to-one name="user"
                    class=“com.cstp.User"
                    property-ref="room"/>
     </class> 

</hibernate-mapping>

在<one-to-one>中,property-ref告诉Hibernate,查询出user并将其参考至room。

一个储存的例子如下:

User user1 = new User();
user1.setName(“tiantian"); 
Room room1 = new Room(); 
room1.setAddress("NTU-M8-419");
user1.setRoom(room1);
        
User user2 = new User(); 
user2.setName(“hhp"); 
Room room2 = new Room(); 
room2.setAddress("NTU-M8-418");
user2.setRoom(room2);

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
 
session.save(user1);
session.save(user2);
        
tx.commit();
session.close();

在查询Room时,User也会一加载,例如:

Session session = sessionFactory.openSession();
Room room = (Room) session.load(Room.class, new Integer(23));
System.out.println(room.getUser().getName());
session.close(); 


上面的查询程序,Hibernate将使用以下的SQL:

Hibernate: select room0_.id as id1_, room0_.address as address1_1_, user1_.id as id0_, user1_.name as name0_0_, user1_.room_id as room3_0_0_ from room room0_ left outer join user user1_ on room0_.id=user1_.room_id where room0_.id=?

一对一(主键关联)

一对一关联的另一种方式,是限制两个实体的主键必须一致,如此直接通过两个表格的主键就可确定一对一关联,而不用额外的外键参考。

例如user与room表格,可以如下建立:

CREATE TABLE user (
    id INT(11) NOT NULL auto_increment PRIMARY KEY,
    name VARCHAR(100) NOT NULL default ''
);

CREATE TABLE room (
    id INT(11) NOT NULL auto_increment PRIMARY KEY,
    address VARCHAR(100) NOT NULL default ''
);

User类别与Room类别的设计使用 一对一(唯一外键关联) 中的设计即可,接着在User.hbm.xml方面如下设计:User.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.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"/> 
 
        <one-to-one name="room" 
                    class=“com.cstp.Room"
                    cascade="all"/>
    </class> 

</hibernate-mapping>

在Room.hbm.xml的设计方面如下:

Room.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.Room" table="room"> 
        <id name="id" column="id"> 
            <generator class="foreign"> 
            <param name="property">user</param>
            </generator>
        </id> 

        <property name="address" 
                  column="address" 
                  type="java.lang.String"/> 
 
        <one-to-one name="user"
                    class=“com.cstp.User"
                    constrained="true"/>
    </class> 

</hibernate-mapping>

在Room的id主键上,使用foreign表示与外键共享主键,也就是与User实体共享主键,而constrained设定为true,表示约束 room的主键必须与user中对应数据的主键相同。

一个储存的实例如下:

User user1 = new User();
user1.setName(“tiantian"); 
Room room1 = new Room(); 
room1.setAddress("NTU-M8-419");
        
// 互相设定关联
user1.setRoom(room1);
room1.setUser(user1);
        
User user2 = new User(); 
user2.setName(“hhp"); 
Room room2 = new Room(); 
room2.setAddress("NTU-M8-418");

// 互相设定关联
user2.setRoom(room2);
room2.setUser(user2);
        
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
 
session.save(user1);
session.save(user2);
        
tx.commit();
session.close();

Hibernate的映射关联关系-多对多

在数据库表格上要进行多对多对应,可以藉由一个中介表格来完成,也就是藉由多对一、一对多来完成多对多关联。

多对多由于使用了中介表格,在查询效率低下,且在程序的对象模式上,多对多会使得对象与对象之间彼此依赖,并不是一个很好的设计方式,在设计上应避免使用多对多关系。

如果一定要使用多对多关系的话,在表格上先如下建立:

CREATE TABLE user (
    id INT(11) NOT NULL auto_increment PRIMARY KEY,
    name VARCHAR(100) NOT NULL default ''
);

CREATE TABLE user_server (
    user_id INT(11),
    server_id INT(11)
);

CREATE TABLE server (
    id INT(11) NOT NULL auto_increment PRIMARY KEY,
    address VARCHAR(100) NOT NULL default ''
);

User.java 

import java.util.Set;

public class User {
    private Integer id;
    private String name;
    private Set servers;
 
    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 Set getServers() {
        return servers;
    }
    public void setServers(Set servers) {
        this.servers = servers;
    }
}

Server.java 

import java.util.Set;

public class Server {
    private Integer id;
    private String address;
    private Set users;
 
    public String getAddress() {
        return address;
    }
     public void setAddress(String address) {
        this.address = address;
    }
     public Integer getId() {
        return id;
    }
     public void setId(Integer id) {
        this.id = id;
    }
     public Set getUsers() {
        return users;
    }
     public void setUsers(Set users) {
        this.users = users;
    }
}

User.hbm.xml 

<hibernate-mapping> 

    <class name=“com.cstp.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"/> 

        <set name="servers" 
             table="user_server" 
             cascade="save-update"> 
 
            <key column="user_id"/> 
            <many-to-many class=“com.cstp.Server" 
                          column="server_id"/> 
        </set> 
    </class> 

</hibernate-mapping>

注意到cascade是设定为save-update,因为在多对多的关系中,很少因为删除其中之一,而所关联的实体都要一并删除的,所以设定save- update,表示在save或update时,一并对关联的对象进行对应的save或update。

Server.hbm.xml的定义如下: Server.hbm.xml 

<hibernate-mapping> 
    <class name=“com.cstp.Server" table="server"> 
        <id name="id" column="id"> 
            <generator class="native"/> 
        </id> 
        <property name="address" type="java.lang.String"/> 
 
        <set name="users" 
             table="user_server" 
             inverse="true" 
             cascade="save-update"> 
 
             <key column="server_id"/> 
             <many-to-many class=“com.cstp.User" 
                           column="user_id"/> 
        </set> 
    </class> 
</hibernate-mapping> 

一个储存时的例子如下:

Server server1 = new Server();
server1.setAddress("PC-219"); 
server1.setUsers(new HashSet());
        
Server server2 = new Server(); 
server2.setAddress("PC-220"); 
server2.setUsers(new HashSet());
        
Server server3 = new Server(); 
server3.setAddress("PC-221");
server3.setUsers(new HashSet());
        
User user1 = new User(); 
user1.setName(“hhp");
user1.setServers(new HashSet());
        
User user2 = new User(); 
user2.setName(“zhangy");
user2.setServers(new HashSet());

// 多对多,互相参考
user1.getServers().add(server1); 
user1.getServers().add(server2); 
user1.getServers().add(server3); 
server1.getUsers().add(user1); 
server2.getUsers().add(user1); 
server3.getUsers().add(user1); 
        
user2.getServers().add(server1); 
user2.getServers().add(server3); 
server1.getUsers().add(user2); 
server3.getUsers().add(user2); 
        
Session session = sessionFactory.openSession(); 
Transaction tx= session.beginTransaction(); 

session.save(user1); 
session.save(user2); 
        
tx.commit();
session.close()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值