Hibernate 3.6.10.Final ²Î¿¼ÊÖ²á ÖÐÎÄ°æ

Hibernate

Hibernate.org Community Documentation

Cat cat = new DomesticCat();
Cat kitten = new DomesticCat();

....
Set kittens = new HashSet();
kittens.add(kitten);
cat.setKittens(kittens);
session.persist(cat);
kittens = cat.getKittens(); // Okay, kittens collection is a Set
(HashSet) cat.getKittens(); // Error!

注意

Use persistent collections the same way you use ordinary Java collections. However, ensure you understand the semantics of bidirectional associations (see 第 7.3.2 节 “双向关联(Bidirectional associations)”).

@Entity

public class Product {
    private String serialNumber;
    private Set<Part> parts = new HashSet<Part>();
    @Id
    public String getSerialNumber() { return serialNumber; }
    void setSerialNumber(String sn) { serialNumber = sn; }
   
    @OneToMany
    @JoinColumn(name="PART_ID")
    public Set<Part> getParts() { return parts; }
    void setParts(Set parts) { this.parts = parts; }
}
@Entity
public class Part {
   ...
}

@Entity

public class Product {
    private String serialNumber;
    private Set<Part> parts = new HashSet<Part>();
    @Id
    public String getSerialNumber() { return serialNumber; }
    void setSerialNumber(String sn) { serialNumber = sn; }
   
    @OneToMany
    @JoinTable(
            name="PRODUCT_PARTS",
            joinColumns = @JoinColumn( name="PRODUCT_ID"),
            inverseJoinColumns = @JoinColumn( name="PART_ID")
    )
    public Set<Part> getParts() { return parts; }
    void setParts(Set parts) { this.parts = parts; }
}
@Entity
public class Part {
   ...
}

<class name="Product">

    <id name="serialNumber" column="productSerialNumber"/>
    <set name="parts">
        <key column="productSerialNumber" not-null="true"/>
        <one-to-many class="Part"/>
    </set>
</class>

  • 一个被包含的实体的实例只能被包含在一个集合的实例中。

  • 一个被包含的实体的实例只能对应于集合索引的一个值中。

<one-to-many
        class=(1)"ClassName"
        not-fo(2)und="ignore|exception"
        entity(3)-name="EntityName"
        node="element-name"
        embed-xml="true|false"
    />

1

class(必需):被关联类的名称。

2

not-found(可选 - 默认为exception):指明若缓存的标示值关联的行缺失,该如何处理:ignore 会把缺失的行作为一个空关联处理。

3

entity-name(可选):被关联的类的实体名,作为 class 的替代。


警告

If the foreign key column of a <one-to-many> association is declared NOT NULL, you must declare the <key> mapping not-null="true" or use a bidirectional association with the collection mapping marked inverse="true". See 第 7.3.2 节 “双向关联(Bidirectional associations)”.

<map
    name="prop(1)ertyName"
    table="tab(2)le_name"
    schema="sc(3)hema_name"
    lazy="true(4)|extra|false"
    inverse="t(5)rue|false"
    cascade="a(6)ll|none|save-update|delete|all-delete-orphan|delete-orphan"
    sort="unso(7)rted|natural|comparatorClass"
    order-by="(8)column_name asc|desc"
    where="arb(9)itrary sql where condition"
    fetch="joi(10)n|select|subselect"
    batch-size(11)="N"
    access="fi(12)eld|property|ClassName"
    optimistic(13)-lock="true|false"
    mutable="t(14)rue|false"
    node="element-name|."
    embed-xml="true|false"
>

    <key .... />
    <map-key .... />
    <element .... />
</map>

1

name:集合属性的名称

2

table(可选——默认为属性的名称)这个集合表的名称(不能在一对多的关联关系中使用)。

3

schema(可选):表的 schema 的名称,他将覆盖在根元素中定义的 schema

4

lazy(可选--默认为 true)可以用来关闭延迟加载(false):指定一直使用预先抓取,或者打开 "extra-lazy" 抓取,此时大多数操作不会初始化集合类(适用于非常大的集合)。

5

inverse(可选 — 默认为 false)标记这个集合作为双向关联关系中的方向一端。

6

cascade(可选 — 默认为 none)让操作级联到子实体。

7

sort(可选)指定集合的排序顺序,其可以为自然的(natural)或者给定一个用来比较的类。

8

order-by (optional): specifies a table column or columns that define the iteration order of the Map, Set or bag, together with an optional asc or desc.

9

where(可选):指定任意的 SQL where 条件,该条件将在重新载入或者删除这个集合时使用(当集合中的数据仅仅是所有可用数据的一个子集时这个条件非常有用)。

10

fetch(可选,默认为 select):用于在外连接抓取、通过后续 select 抓取和通过后续 subselect 抓取之间选择。

11

batch-size(可选,默认为 1):指定通过延迟加载取得集合实例的批处理块大小("batch size")。

12

access(可选-默认为属性 property):Hibernate 取得集合属性值时使用的策略。

13

乐观锁(可选 - 默认为 true):对集合的状态的改变会是否导致其所属的实体的版本增长(对一对多关联来说,关闭这个属性常常是有理的)。

14

mutable(可变)(可选 — 默认为 true):若值为 false,表明集合中的元素不会改变(在某些情况下可以进行一些小的性能优化)。


@JoinColumn(nullable=false)
<key column="productSerialNumber" not-null="true"/>
<key column="productSerialNumber" on-delete="cascade"/>
@OnDelete(action=OnDeleteAction.CASCADE)
  • as ordered lists, where the order is not materialized in the database

  • as indexed lists, where the order is materialized in the database

@Entity

public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   @OneToMany(mappedBy="customer")
   @OrderBy("number")
   public List<Order> getOrders() { return orders; }
   public void setOrders(List<Order> orders) { this.orders = orders; }
   private List<Order> orders;
}
@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;
   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}
-- Table schema
|-------------| |----------|
| Order       | | Customer |
|-------------| |----------|
| id          | | id       |
| number      | |----------| 
| customer_id |
|-------------|

@Entity

public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   @OneToMany(mappedBy="customer")
   @OrderColumn(name="orders_index")
   public List<Order> getOrders() { return orders; }
   public void setOrders(List<Order> orders) { this.orders = orders; }
   private List<Order> orders;
}
@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;
   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}
-- Table schema
|--------------| |----------|
| Order        | | Customer |
|--------------| |----------|
| id           | | id       |
| number       | |----------| 
| customer_id  |
| orders_order |
|--------------|

注意

We recommend you to convert the legacy @org.hibernate.annotations.IndexColumn usages to @OrderColumn unless you are making use of the base property. The base property lets you define the index value of the first element (aka as base index). The usual value is 0 or 1. The default is 0 like in Java.

<list-index
        column(1)="column_name"
        base="(2)0|1|..."/>

1

column_name(必需):持有集合索引值的字段的名称。

1

base(可选 — 默认为 0)对应列表或队列的第一个元素的索引字段的值。


@Entity

public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   @OneToMany(mappedBy="customer")
   @MapKey(name="number")
   public Map<String,Order> getOrders() { return orders; }
   public void setOrders(Map<String,Order> order) { this.orders = orders; }
   private Map<String,Order> orders;
}
@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;
   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}
-- Table schema
|-------------| |----------|
| Order       | | Customer |
|-------------| |----------|
| id          | | id       |
| number      | |----------| 
| customer_id |
|-------------|

  • @MapKeyColumn if the map key is a basic type. If you don't specify the column name, the name of the property followed by underscore followed by KEY is used (for example orders_KEY).

  • @MapKeyEnumerated / @MapKeyTemporal if the map key type is respectively an enum or a Date.

  • @MapKeyJoinColumn/@MapKeyJoinColumns if the map key type is another entity.

  • @AttributeOverride/@AttributeOverrides when the map key is a embeddable object. Use key. as a prefix for your embeddable object property names.

@Entity

public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   @OneToMany @JoinTable(name="Cust_Order")
   @MapKeyColumn(name="orders_number")
   public Map<String,Order> getOrders() { return orders; }
   public void setOrders(Map<String,Order> orders) { this.orders = orders; }
   private Map<String,Order> orders;
}
@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;
   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}
-- Table schema
|-------------| |----------| |---------------|
| Order       | | Customer | | Cust_Order    |
|-------------| |----------| |---------------|
| id          | | id       | | customer_id   |
| number      | |----------| | order_id      |
| customer_id |              | orders_number |
|-------------|              |---------------|

注意

We recommend you to migrate from @org.hibernate.annotations.MapKey / @org.hibernate.annotation.MapKeyManyToMany to the new standard approach described above

<map-key
        column(1)="column_name"
        formul(2)a="any SQL expression"
        type="(3)type_name"
        node="@attribute-name"
        length="N"/>

1

column(可选):持有集合索引值的字段的名称。

2

formula(可选):用于对表键求值的 SQL 公式。

3

type(必需):映射键的类型。


<map-key-many-to-many
        column(1)="column_name"
        formul(2)(3)a="any SQL expression"
        class="ClassName"
/>

1

column(可选):用于集合索引值的外键字段的名称。

2

formula(可选):用于对映射键的外键求值的 SQL 公式。

3

class(必需):用作映射键的实体类的名称。


@Entity

public class User {
   [...]
   public String getLastname() { ...}
   @ElementCollection
   @CollectionTable(name="Nicknames", joinColumns=@JoinColumn(name="user_id"))
   @Column(name="nickname")
   public Set<String> getNicknames() { ... } 
}

@Entity

public class User {
   [...]
   public String getLastname() { ...}
   @ElementCollection
   @CollectionTable(name="Addresses", joinColumns=@JoinColumn(name="user_id"))
   @AttributeOverrides({
      @AttributeOverride(name="street1", column=@Column(name="fld_street"))
   })
   public Set<Address> getAddresses() { ... } 
}
@Embeddable
public class Address {
   public String getStreet1() {...}
   [...]
}

注意

in @AttributeOverride, you must use the value. prefix to override properties of the embeddable object used in the map value and the key. prefix to override properties of the embeddable object used in the map key.

@Entity

public class User {
   @ElementCollection
   @AttributeOverrides({
      @AttributeOverride(name="key.street1", column=@Column(name="fld_street")),
      @AttributeOverride(name="value.stars", column=@Column(name="fld_note"))
   })
   public Map<Address,Rating> getFavHomes() { ... }

注意

We recommend you to migrate from @org.hibernate.annotations.CollectionOfElements to the new @ElementCollection annotation.

<element
        column(1)="column_name"
        formul(2)a="any SQL expression"
        type="(3)typename"
        length="L"
        precision="P"
        scale="S"
        not-null="true|false"
        unique="true|false"
        node="element-name"
/>

1

column(可选):持有集合元素值的字段的名称。

2

formula(可选):用于对元素求值的 SQL 公式。

3

type(必需):集合元素的类型。


@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)

@JoinColumn(name="CUST_ID")
@Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)
public SortedSet<Ticket> getTickets() {
    return tickets;
}

<set name="aliases"
            table="person_aliases" 
            sort="natural">
    <key column="person"/>
    <element column="name" type="string"/>
</set>

<map name="holidays" sort="my.custom.HolidayComparator">
    <key column="year_id"/>
    <map-key column="hol_name" type="string"/>
    <element column="hol_date" type="date"/>
</map>

提示

分类集合的行为事实上象 java.util.TreeSet 或者 java.util.TreeMap

<set name="aliases" table="person_aliases" order-by="lower(name) asc">
    <key column="person"/>
    <element column="name" type="string"/>
</set>

<map name="holidays" order-by="hol_date, hol_name">
    <key column="year_id"/>
    <map-key column="hol_name" type="string"/>
    <element column="hol_date type="date"/>
</map>

注意

注意:这个 order-by 属性的值是一个 SQL 排序子句而不是 HQL 的。

              
              sortedUsers 
              
              =
              
               s
              
              .
              
              createFilter
              
              (
              
               group
              
              .
              
              getUsers
              
              (),
              
               
              
              "order by this.name"
              
               
              
              ).
              
              list
              
              ();
            

@Entity

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

@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() {
    ...
}

<class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <set name="children" inverse="true">
        <key column="parent_id"/>
        <one-to-many class="Child"/>
    </set>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        not-null="true"/>
</class>

@Entity

public class Employer implements Serializable {
    @ManyToMany(
        targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
        cascade={CascadeType.PERSIST, CascadeType.MERGE}
    )
    @JoinTable(
        name="EMPLOYER_EMPLOYEE",
        joinColumns=@JoinColumn(name="EMPER_ID"),
        inverseJoinColumns=@JoinColumn(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;
    }
}                

@Entity

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

@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() {
        ...
    }
}             

注意

You cannot select an indexed collection.

<class name="Category">
    <id name="id" column="CATEGORY_ID"/>
    ...
    <bag name="items" table="CATEGORY_ITEM">
        <key column="CATEGORY_ID"/>
        <many-to-many class="Item" column="ITEM_ID"/>
    </bag>
</class>

<class name="Item">
    <id name="id" column="ITEM_ID"/>
    ...

    <!-- inverse end -->
    <bag name="categories" table="CATEGORY_ITEM" inverse="true">
        <key column="ITEM_ID"/>
        <many-to-many class="Category" column="CATEGORY_ID"/>
    </bag>
</class>

category.getItems().add(item);           // The category now "knows" about the relationship

item.getCategories().add(category);      // The item now "knows" about the relationship
session.persist(item);                   // The relationship won't be saved!
session.persist(category);               // The relationship will be saved

<class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <map name="children" inverse="true">
        <key column="parent_id"/>
        <map-key column="name" 
            type="string"/>
        <one-to-many class="Child"/>
    </map>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <property name="name" 
        not-null="true"/>
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        not-null="true"/>
</class>

<class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <map name="children">
        <key column="parent_id"
            not-null="true"/>
        <map-key column="name" 
            type="string"/>
        <one-to-many class="Child"/>
    </map>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        insert="false"
        update="false"
        not-null="true"/>
</class>

@Entity
public class Company {
   @Id 
   int id;
   ...
   @OneToMany // unidirectional
   @MapKeyJoinColumn(name="employee_id")
   Map<EmployeeContract> contracts;
}

// or

<map name="contracts">
    <key column="employer_id" not-null="true"/>
    <map-key-many-to-many column="employee_id" class="Employee"/>
    <one-to-many class="Contract"/>
</map>

<idbag name="lovers" table="LOVERS">
    <collection-id column="ID" type="long">
        <generator class="sequence"/>
    </collection-id>
    <key column="PERSON1"/>
    <many-to-many column="PERSON2" class="Person" fetch="join"/>
</idbag>
public class Parent {

    private long id;
    private Set<Child> children;
    // getter/setter
    ...
}
public class Child {
   private long id;
   private String name
   
   // getter/setter
   ...
}

public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;
   private String name;

   
   // getter/setter
   ...
}

<hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children">
            <key column="parent_id"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping>

create table parent ( id bigint not null primary key )
create table child ( id bigint not null primary key, name varchar(255), parent_id bigint )
alter table child add constraint childfk0 (parent_id) references parent

public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany(mappedBy="parent")
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;

   private String name;
 
   @ManyToOne
   private Parent parent;

   
   // getter/setter
   ...
}

<hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children" inverse="true">
            <key column="parent_id"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
        <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/>
    </class>

</hibernate-mapping>

create table parent ( id bigint not null primary key )
create table child ( id bigint not null
                     primary key,
                     name varchar(255),
                     parent_id bigint not null )
alter table child add constraint childfk0 (parent_id) references parent

public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany(optional=false)
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;
   private String name;

   
   // getter/setter
   ...
}

<hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children">
            <key column="parent_id" not-null="true"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping>

public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @ManyToMany
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;

   private String name;

   
   // getter/setter
   ...
}

<hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children" table="childset">
            <key column="parent_id"/>
            <many-to-many class="Child" column="child_id"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping>

create table parent ( id bigint not null primary key )
create table child ( id bigint not null primary key, name varchar(255) )
create table childset ( parent_id bigint not null,
                        child_id bigint not null,
                        primary key ( parent_id, child_id ) )
alter table childset add constraint childsetfk0 (parent_id) references parent
alter table childset add constraint childsetfk1 (child_id) references child