hibernate的Many2One、Many2Many等的使用

本文简单讲述hibernate的Many2One、One2Many和Many2Many的单双向映射的annotation和xml的实现方式。

1.首先,先看下annotation的API文档

2.2.5.2. 多对一(Many-to-one)

在实体属性一级使用@ManyToOne注解来定义多对一关联:

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
        return company;
    }
    ...
}
            

其中@JoinColumn是可选的,关联字段默认值和一对一 (one to one)关联的情况相似, 列名为:主体的关联属性名+下划线+被关联端的主键列名. 在这个例子中是company_id,
因为关联的属性是companyCompany的主键是id.

@ManyToOne注解有一个名为targetEntity的参数,
该参数定义了目标实体名.通常不需要定义该参数, 因为在大部分情况下默认值(表示关联关系的属性类型)就可以很好的满足要求了. 不过下面这种情况下这个参数就显得有意义了:使用接口作为返回值而不是常见的实体.

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity=CompanyImpl.class )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
        return company;
    }
    ...
}

public interface Company {
    ...
            

对于多对一也可以通过关联表的方式来映射。 通过@JoinTable注解可定义关联表, 该关联表包含了指回实体表的外键(通过@JoinTable.joinColumns)
以及指向目标实体表的外键(通过@JoinTable.inverseJoinColumns).

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinTable(name="Flight_Company",
        joinColumns = @JoinColumn(name="FLIGHT_ID"),
        inverseJoinColumns = @JoinColumn(name="COMP_ID")
    )
    public Company getCompany() {
        return company;
    }
    ...
}
2.2.5.3.2. 一对多(One-to-many)

在属性级使用 @OneToMany注解可定义一对多关联.一对多关联可以是双向关联.

2.2.5.3.2.1. 双向(Bidirectional)

在EJB3规范中多对一这端几乎总是双向关联中的主体(owner)端, 而一对多这端的关联注解为@OneToMany( mappedBy=... )

@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
}              

Troop 通过troop 属性和Soldier建立了一对多的双向关联.
mappedBy端不必也不能再定义任何物理映射

对于一对多的双向映射,如果要一对多这一端维护关联关系, 你需要删除mappedBy元素并将多对一这端的 @JoinColumn的insertable和updatable设置为false.
很明显,这种方案不会得到什么明显的优化,而且还会增加一些附加的UPDATE语句.

@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}
2.2.5.3.2.2. 单向(Unidirectional)

通过在被拥有的实体端(owned entity)增加一个外键列来实现一对多单向关联是很少见的,也是不推荐的. 我们强烈建议通过一个联接表(join table)来实现这种关联(下一节会对此进行解释). 可以通过@JoinColumn注解来描述这种单向关联关系.

@Entity
public class Customer implements Serializable {
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="CUST_ID")
    public Set<Ticket> getTickets() {
    ...
}

@Entity
public class Ticket implements Serializable {
    ... //no bidir
}
               

Customer 通过 CUST_ID列和Ticket 建立了单向关联关系.

2.2.5.3.2.3. 通过关联表处理单向关联

通过联接表处理单向一对多关联是首选方式.这种关联通过@JoinTable注解来进行描述.

@Entity
public class Trainer {
    @OneToMany
    @JoinTable(
            name="TrainedMonkeys",
            joinColumns = @JoinColumn( name="trainer_id"),
            inverseJoinColumns = @JoinColumn( name="monkey_id")
    )
    public Set<Monkey> getTrainedMonkeys() {
    ...
}

@Entity
public class Monkey {
    ... //no bidir
}
               

上面这个例子中,Trainer通过 TrainedMonkeys表和 Monkey 建立了单向关联.
其中外键trainer_id关联到Trainer (joinColumns),
而外键monkey_id关联到 Monkey (inversejoinColumns).

2.2.5.3.2.4. 默认处理机制

通过联接表来建立单向一对多关联不需要描述任何物理映射. 表名由以下三个部分组成:主表(owner table)表名+下划线+从表(the other side table)表名. 指向主表的外键名:主表表名+下划线+主表主键列名 指向从表的外键名:主表所对应实体的属性名+下划线+从表主键列名 指向从表的外键定义为唯一约束,用来表示一对多的关联关系.

@Entity
public class Trainer {
    @OneToMany
    public Set<Tiger> getTrainedTigers() {
    ...
}

@Entity
public class Tiger {
    ... //no bidir
}
               

上面这个例子中,TrainerTiger 通过联接表 Trainer_Tiger建立单向关联关系,
其中外键trainer_id关联到Trainer (主表表名, _(下划线),
trainer id), 而外键trainedTigers_id关联到Tiger (属性名称, _(下划线),
Tiger表的主键列名).

2.2.5.3.3. 多对多(Many-to-many)
2.2.5.3.3.1. 定义

你可以通过@ManyToMany注解可定义的多对多关联. 同时,你也需要通过注解@JoinTable描述关联表和关联条件. 如果是双向关联,其中一段必须定义为owner,另一端必须定义为inverse(在对关联表进行更新操作时这一端将被忽略):

@Entity
public class Employer implements Serializable {
    @ManyToMany(
        targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
        cascade={CascadeType.PERSIST, CascadeType.MERGE}
    )
    @JoinTable(
        name="EMPLOYER_EMPLOYEE",
        [email protected](name="EMPER_ID"),
        [email protected](name="EMPEE_ID")
    )
    public Collection getEmployees() {
        return employees;
    }
    ...
}
               
@Entity
public class Employee implements Serializable {
    @ManyToMany(
        cascade = {CascadeType.PERSIST, CascadeType.MERGE},
        mappedBy = "employees",
        targetEntity = Employer.class
    )
    public Collection getEmployers() {
        return employers;
    }
}
               

至此,我们已经展示了很多跟关联有关的声明定义以及属性细节. 下面我们将深入介绍@JoinTable注解,该注解定义了联接表的表名, 联接列数组(注解中定义数组的格式为{ A, B, C }), 以及inverse联接列数组. 后者是关联表中关联到Employee主键的列(the
"other side").

正如前面所示,被关联端不必也不能描述物理映射: 只需要一个简单的mappedBy参数,该参数包含了主体端的属性名,这样就绑定双方的关系.

2.2.5.3.3.2. 默认值

和其他许多注解一样,在多对多关联中很多值是自动生成. 当双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值. 关联表名:主表表名+_下划线+从表表名, 关联到主表的外键名:主表名+_下划线+主表中的主键列名. 关联到从表的外键名:主表中用于关联的属性名+_下划线+从表的主键列名.
以上规则对于双向一对多关联同样有效.

@Entity
public class Store {
    @ManyToMany(cascade = CascadeType.PERSIST)
    public Set<City> getImplantedIn() {
        ...
    }
}

@Entity
public class City {
    ... //no bidirectional relationship
}
               

上面这个例子中,Store_Table作为联接表. Store_id列是联接到Store表的外键.
implantedIn_id列则联接到City表.

当双向多对多关联中没有定义任何物理映射时, Hibernate根据以下规则生成相应的值 关联表名: :主表表名+_下划线+从表表名, 关联到主表的外键名:从表用于关联的属性名+_下划线+主表中的主键列名. 关联到从表的外键名:主表用于关联的属性名+_下划线+从表的主键列名.
以上规则对于双向一对多关联同样有效.

@Entity
public class Store {
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    public Set<Customer> getCustomers() {
        ...
    }
}

@Entity
public class Customer {
    @ManyToMany(mappedBy="customers")
    public Set<Store> getStores() {
        ...
    }
}
               

在上面这个例子中,Store_Customer作为联接表. stores_id列是联接到Store表的外键,
customers_id列联接到City表.

2.再来看下xml的API文档

7.2. 单向关联(Unidirectional associations)

7.2.1. Many-to-one

单向many-to-one关联是最常见的单向关联关系。

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address"
        column="addressId"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )

7.2.3. One-to-many

unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses">
        <key column="personId"
            not-null="true"/>
        <one-to-many class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not null )

You should instead use a join table for this kind of association.

7.3. 使用连接表的单向关联(Unidirectional associations with join tables)

7.3.1. One-to-many

unidirectional one-to-many association on a join table is the preferred option. Specifying unique="true",
changes the multiplicity from many-to-many to one-to-many.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            unique="true"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )

7.3.2. Many-to-one

unidirectional many-to-one association on a join table is common when the association is optional. For example:

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress"
        optional="true">
        <key column="personId" unique="true"/>
        <many-to-one name="address"
            column="addressId"
            not-null="true"/>
    </join>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )

7.3.4. Many-to-many

Finally, here is an example of a unidirectional many-to-many association.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )

7.4. 双向关联(Bidirectional associations)

7.4.1. one-to-many / many-to-one

bidirectional many-to-one association is the most common kind of association. The following example illustrates the standard parent/child relationship.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address"
        column="addressId"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true">
        <key column="addressId"/>
        <one-to-many class="Person"/>
    </set>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )

If you use a List, or other indexed collection, set the key column
of the foreign key to not null. Hibernate will manage the association from the collections side to maintain the index of each element, making
the other side virtually inverse by setting update="false" and insert="false":

<class name="Person">
   <id name="id"/>
   ...
   <many-to-one name="address"
      column="addressId"
      not-null="true"
      insert="false"
      update="false"/>
</class>

<class name="Address">
   <id name="id"/>
   ...
   <list name="people">
      <key column="addressId" not-null="true"/>
      <list-index column="peopleIdx"/>
      <one-to-many class="Person"/>
   </list>
</class>

If the underlying foreign key column is NOT NULL, it is important that you
define not-null="true" on the<key> element
of the collection mapping. Do not only declare not-null="true" on a possible nested <column>element,
but on the <key> element.

7.5. 使用连接表的双向关联(Bidirectional associations with join tables)

7.5.1. one-to-many / many-to-one

The following is an example of a bidirectional one-to-many association on a join table. The inverse="true" can
go on either end of the association, on the collection, or on the join.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses"
        table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            unique="true"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress"
        inverse="true"
        optional="true">
        <key column="addressId"/>
        <many-to-one name="person"
            column="personId"
            not-null="true"/>
    </join>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )

7.5.3. Many-to-many

Here is an example of a bidirectional many-to-many association.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true" table="PersonAddress">
        <key column="addressId"/>
        <many-to-many column="personId"
            class="Person"/>
    </set>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )

3.Many2One单向映射的annotation版本

使用Group和User,二者为多对一的关系,即一个Group有多个User,多个User对应一个Group

需要在User中引用Group,并在getGroup使用@ManyToOne

Group

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	private Group group ;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
}

使用JUnit进行测试,OrMappingTest.java,注意此类在之后的测试中通用

package com.baosight.model;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class OrMappingTest {
	private static SessionFactory sf = null;
	@BeforeClass
	public static void beforeClass(){
		// 读取配置文件
		Configuration cfg = new AnnotationConfiguration();
		// 得到session工厂
		sf = cfg.configure().buildSessionFactory();
	}
	@Test
	public void testSchemaExport() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
	}
	@AfterClass
	public static void afterClass(){
		// 关闭session工厂
		sf.close();
	}
}

测试结果为:

4.Many2One单向映射的xml版本

使用School和Student,二者为多对一的关系,即一个School有多个Student,多个Student对应一个School

需要在Student中引用School,并在Student.hbm.xml使用<many-to-one name="school" column="schoolId"></many-to-one>

School

package com.baosight.model;

public class School {
	private String id;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

Student

package com.baosight.model;

public class Student {
	private String id;
	private String num;
	private School school;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public School getSchool() {
		return school;
	}
	public void setSchool(School school) {
		this.school = school;
	}

}

School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<many-to-one name="school" column="schoolId"></many-to-one>
</class>
</hibernate-mapping>

测试结果为:

5.One2Many单向映射的annotation版本

使用Group和User,二者为一对多的关系,即一个Group有多个User,多个User对应一个Group

需要在Group中引用User的集合Set<User> users,并在getUsers使用@OneToMany

@JoinColumn(name="groupId")

Group

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	private Set<User> users;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany
	@JoinColumn(name="groupId")
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}

User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

测试结果为:

6.One2Many单向映射的xml版本

使用School和Student,二者为一对多的关系,即一个School有多个Student,多个Student对应一个School

需要在School中引用Student的集合Set<Student> students,并在School.hbm.xml使用<set name="students">

<key column="schoolId"/>

<one-to-many class="Student"/>

</set>

School

package com.baosight.model;

import java.util.Set;

public class School {
	private String id;
	private String name;
	private Set<Student> students;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}

Student

package com.baosight.model;

public class Student {
	private String id;
	private String num;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}

School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
</class>
</hibernate-mapping>

测试结果为:

7.Many2One/One2Many双向映射的annotation版本

使用Group和User,二者为多对一的关系,即一个Group有多个User,多个User对应一个Group

需要在User中引用Group,并在getGroup使用@ManyToOne

还需要在Group中引用User的集合Set<User> users,并在getUsers使用@OneToMany(mappedBy="group"),mappedBy表示映射关系由User中的group来维持

Group

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	private Set<User> users;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany(mappedBy="group")
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}

User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	private Group group;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
}

测试结果为:

8.Many2One/One2Many双向映射的xml版本

使用School和Student,二者为多对一的关系,即一个School有多个Student,多个Student对应一个School

需要在Student中引用School,并在Student.hbm.xml使用<many-to-one name="school" column="schoolId"></many-to-one>

还需要需要在School中引用Student的集合Set<Student> students,并在School.hbm.xml使用<set name="students">

<key column="schoolId"/>

<one-to-many class="Student"/>

</set>

School

package com.baosight.model;

import java.util.Set;

public class School {
	private String id;
	private String name;
	private Set<Student> students;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}

Student

package com.baosight.model;

public class Student {
	private String id;
	private String num;
	private School school;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public School getSchool() {
		return school;
	}
	public void setSchool(School school) {
		this.school = school;
	}
}

School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<many-to-one name="school" column="schoolId"></many-to-one>
</class>
</hibernate-mapping>

测试结果:

9.Many2Many单向映射的annotation版本

使用Teacher和Student,二者为多对多的关系,即一个Teacher有多个Student,一个Student对应多个Teacher

本例单向的意思是Teacher引用Student的集合Set<Student> students,并在getStudents使用@ManyToMany

@JoinTable(name="t_s",

joinColumns={@JoinColumn(name="teacher_id")},

inverseJoinColumns={@JoinColumn(name="student_id")}

)

Teacher

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
public class Teacher {
	private String id;
	private String name;
	private Set<Student> students;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany
	@JoinTable(name="t_s",
	joinColumns={@JoinColumn(name="teacher_id")},
	inverseJoinColumns={@JoinColumn(name="student_id")}
	)
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}

Student

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
public class Student {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

测试结果为:

10.Many2Many单向映射的xml版本

使用Order和Product,二者为多对多的关系,即一个Order有多个Product,一个Product对应多个Order

本例单向的意思是需要在Order中引用Product的集合Set<Product> products,并在Order.hbm.xml使用

<set name="products" table="order_pro">

<key column="orderId"/>

<many-to-many class="Product" column="productId"/>

</set>

Order

package com.baosight.model;

import java.util.Set;

public class Order {
	private String id;
	private String name;
	private Set<Product> products;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Product> getProducts() {
		return products;
	}
	public void setProducts(Set<Product> products) {
		this.products = products;
	}
}

Product

package com.baosight.model;

public class Product {
	private String id;
	private String num;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}

Order.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Order" table="t_order" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>
</class>
</hibernate-mapping>

Product.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Product" table="t_product" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
</class>
</hibernate-mapping>

测试结果为:

11.Many2Many双向映射的annotation版本

使用Teacher和Student,二者为多对多的关系,即一个Teacher有多个Student,一个Student对应多个Teacher

需要在Teacher引用Student的集合Set<Student> students,并在getStudents使用@ManyToMany

@JoinTable(name="t_s",

joinColumns={@JoinColumn(name="teacher_id")},

inverseJoinColumns={@JoinColumn(name="student_id")}

)

还需要在在Student引用Teacher的集合Set<Teacher> teachers,并在getTeachers使用@ManyToMany(mappedBy="students"),其中mappedBy表示映射关系由Teacher中的students来管理

Teacher

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
public class Teacher {
	private String id;
	private String name;
	private Set<Student> students;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany
	@JoinTable(name="t_s",
	joinColumns={@JoinColumn(name="teacher_id")},
	inverseJoinColumns={@JoinColumn(name="student_id")}
	)
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}

Student

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
public class Student {
	private String id;
	private String name;
	private Set<Teacher> teachers;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany(mappedBy="students")
	public Set<Teacher> getTeachers() {
		return teachers;
	}
	public void setTeachers(Set<Teacher> teachers) {
		this.teachers = teachers;
	}
}

测试结果为:

12.Many2Many双向映射的xml版本

使用Order和Product,二者为多对多的关系,即一个Order有多个Product,一个Product对应多个Order

需要在Order中引用Product的集合Set<Product> products,并在Order.hbm.xml使用

<set name="products" table="order_pro">

<key column="orderId"/>

<many-to-many class="Product" column="productId"/>

</set>

还需要在

需要在Product中引用Order的集合Set<Order> orders,并在Product.hbm.xml使用

<set name="orders" table="order_pro">

<key column="productId"/>

<many-to-many class="Order" column="orderId"/>

</set>

Order

package com.baosight.model;

import java.util.Set;

public class Order {
	private String id;
	private String name;
	private Set<Product> products;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Product> getProducts() {
		return products;
	}
	public void setProducts(Set<Product> products) {
		this.products = products;
	}
}

Product

package com.baosight.model;

import java.util.Set;

public class Product {
	private String id;
	private String num;
	private Set<Order> orders;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public Set<Order> getOrders() {
		return orders;
	}
	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}
}

Order.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Order" table="t_order" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>
</class>
</hibernate-mapping>

Product.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Product" table="t_product" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<set name="orders" table="order_pro">
<key column="productId"/>
<many-to-many class="Order" column="orderId"/>
</set>
</class>
</hibernate-mapping>

测试结果:

以上即为hibernate的Many2One/One2Many/Many2Many的内容,值得一提的是在实际的使用中多使用Many2One/One2Many,而Many2Many使用的不多。总之,这些映射关系需要在实际的使用中仔细体会。

时间: 2024-10-01 05:25:38

hibernate的Many2One、Many2Many等的使用的相关文章

hibernate之 10.many2many单向

在前文hibernate之5.many2one单向提到多对多关系,表结构设计是基于中间表来实现, 下面以用户与角色(多对多)为例,在Hibernate是如何操作的 表结构设计: 类图: CRUD; Student package com.demo.model; import java.io.UnsupportedEncodingException; import java.util.Set; /**学生信息 * @author wobendiankun *2014-10-19 下午08:54:2

hibernate之12.many2many变形

多对多关系中,中间表t_user_role不能添加额外的内容,如;创建时间,修改时间,操作员工员等等 我们可以通过另一种方式,多对一来解决. 首先来看一个类图, 图1:用户与角色关系 从图1中,我们发现: User类与UserRole类是 一对多关系, Role类与UserRole也是一对多关系 通过UserRole类,我们可得到User类与Role类是多对多关系 CRUD: UserRole package com.demo.model; import java.util.Set; /**用户

hibernate之 11.many2many双向

表结构: 类图: CRUD: User package com.demo.model; import java.util.Set; /**用户信息 * @author wobendiankun *2014-10-29 下午11:05:26 */ public class User { /** *用户Id */ private int userId; /** * 用户名 */ private String userName; /** * 密码 */ private String password;

hibernate它 11.many2many双向

表结构: 类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd29iZW5kaWFua3Vu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > CRUD: User package com.demo.model; import java.util.Set; /**用户信息 * @author wobendiankun *2014-10-29 下

mybatis中many2one

上一章我们讲到,如果说hibernate是面向对象为主,关系为辅,那么在mybatis中则是着重考虑的是关系模型,换句话说,如果对象模型设计的不好,就会很容易的感觉到实现的难度. 首先来看看最简单的单向many2one: 建立对象: public class Customer {     private Long id;     private String name; } public class Orders {     private Long id;     private String

OpenERP对象字段定义的详解

OpenERP对象支持的字段类型有,基础类型:char, text, boolean, integer, float, date, time, datetime, binary:复杂类型:selection, function, related:关系类型:one2one, one2many, many2one, many2many.下面逐一说明. boolean: 布尔型(true, false) integer: 整数. float: 浮点型,如 'rate' : fields.float('

odoo之ERP系统

p { line-height: 120% } a:link { } odoo大纲 第一部分:数据库postgressql 大象 第二部分:ORM(API) 第三部分:客户端 用python软件写: .py文件 包含两部分:1.自定义部分,由自己写,定义类和功能. 2.继承部分,针对的是原生的模块,继承他原有的功能,添加新的方法. .xml文件 视图部分:最常用的是form视图和tree视图,等等其他视图,还有页签和其他控件按钮 p { line-height: 120% } a:link {

Domain 表达式的用法

什么是Domain [('create_uid','=',user.id)] Domain是个多条件的列表,每个条件是一个三元表达式:[(字段名,操作符,值), (字段名,操作符,值)] Domain使用场合 权限管理中的行级权限 tree视图的过滤器 其它学习到了再补充 字段名 当前模型的字段或者是通过点操作符访问当前模型的Many2one / Many2Many对象.如果左边是Many2Many对象的时候,则表示左边只要任意一个值符合条件则符合条件. 操作符 名称 说明 =,!=,>,>=

doamin 过滤条件

doamin 过滤条件 在odoo中,通过domain来过滤数据记录 domain是一个list,里面有多个条件 条件是一个有3个元素的元祖 ('字段名','比较操作符','值') 字段名 当前模型的字段或者是通过点操作符访问当前模型的Many2one / Many2Many对象.如果左边是Many2Many对象的时候,则表示左边只要任意一个值符合条件则符合条件. 比较操作符 操作符 含义 = 等于 != 不等于 >= 大于等于 > 大于 <= 小于等于 like 模糊查询 ilike