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

Hibernate

Hibernate.org Community Documentation

  • using Java 5 annotations (via the Java Persistence 2 annotations)

  • using JPA 2 XML deployment descriptors (described in chapter XXX)

  • using the Hibernate legacy XML files approach known as hbm.xml

package eg;

@Entity 

@Table(name="cats") @Inheritance(strategy=SINGLE_TABLE)
@DiscriminatorValue("C") @DiscriminatorColumn(name="subclass", discriminatorType=CHAR)
public class Cat {
   
   @Id @GeneratedValue
   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;
   public BigDecimal getWeight() { return weight; }
   public void setWeight(BigDecimal weight) { this.weight = weight; }
   private BigDecimal weight;
   @Temporal(DATE) @NotNull @Column(updatable=false)
   public Date getBirthdate() { return birthdate; }
   public void setBirthdate(Date birthdate) { this.birthdate = birthdate; }
   private Date birthdate;
   @org.hibernate.annotations.Type(type="eg.types.ColorUserType")
   @NotNull @Column(updatable=false)
   public ColorType getColor() { return color; }
   public void setColor(ColorType color) { this.color = color; }
   private ColorType color;
   @NotNull @Column(updatable=false)
   public String getSex() { return sex; }
   public void setSex(String sex) { this.sex = sex; }
   private String sex;
   @NotNull @Column(updatable=false)
   public Integer getLitterId() { return litterId; }
   public void setLitterId(Integer litterId) { this.litterId = litterId; }
   private Integer litterId;
   @ManyToOne @JoinColumn(name="mother_id", updatable=false)
   public Cat getMother() { return mother; }
   public void setMother(Cat mother) { this.mother = mother; }
   private Cat mother;
   @OneToMany(mappedBy="mother") @OrderBy("litterId")
   public Set<Cat> getKittens() { return kittens; }
   public void setKittens(Set<Cat> kittens) { this.kittens = kittens; }
   private Set<Cat> kittens = new HashSet<Cat>();
}
@Entity @DiscriminatorValue("D")
public class DomesticCat extends Cat {
   public String getName() { return name; }
   public void setName(String name) { this.name = name }
   private String name;
}
@Entity
public class Dog { ... }
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="eg">

        <class name="Cat"
            table="cats"
            discriminator-value="C">

                <id name="id">
                        <generator class="native"/>
                </id>

                <discriminator column="subclass"
                     type="character"/>

                <property name="weight"/>

                <property name="birthdate"
                    type="date"
                    not-null="true"
                    update="false"/>

                <property name="color"
                    type="eg.types.ColorUserType"
                    not-null="true"
                    update="false"/>

                <property name="sex"
                    not-null="true"
                    update="false"/>

                <property name="litterId"
                    column="litterId"
                    update="false"/>

                <many-to-one name="mother"
                    column="mother_id"
                    update="false"/>

                <set name="kittens"
                    inverse="true"
                    order-by="litter_id">
                        <key column="mother_id"/>
                        <one-to-many class="Cat"/>
                </set>

                <subclass name="DomesticCat"
                    discriminator-value="D">

                        <property name="name"
                            type="string"/>

                </subclass>

        </class>

        <class name="Dog">
                <!-- mapping for Dog could go here -->
        </class>

</hibernate-mapping>
@Entity

public class Flight implements Serializable {
    Long id;
    @Id
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
}         
@Entity

@Table(name="TBL_FLIGHT", 
       schema="AIR_COMMAND", 
       uniqueConstraints=
           @UniqueConstraint(
               name="flight_number", 
               columnNames={"comp_prefix", "flight_number"} ) )
public class Flight implements Serializable {
    @Column(name="comp_prefix")
    public String getCompagnyPrefix() { return companyPrefix; }
    @Column(name="flight_number")
    public String getNumber() { return number; }
}
  • dynamicInsert / dynamicUpdate (defaults to false): specifies that INSERT / UPDATE SQL should be generated at runtime and contain only the columns whose values are not null. The dynamic-update and dynamic-insert settings are not inherited by subclasses. Although these settings can increase performance in some cases, they can actually decrease performance in others.

  • selectBeforeUpdate (defaults to false): specifies that Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified. Only when a transient object has been associated with a new session using update(), will Hibernate perform an extra SQL SELECT to determine if an UPDATE is actually required. Use of select-before-update will usually decrease performance. It is useful to prevent a database update trigger being called unnecessarily if you reattach a graph of detached instances to a Session.

  • polymorphisms (defaults to IMPLICIT): determines whether implicit or explicit query polymorphisms is used. Implicit polymorphisms means that instances of the class will be returned by a query that names any superclass or implemented interface or class, and that instances of any subclass of the class will be returned by a query that names the class itself. Explicit polymorphisms means that class instances will be returned only by queries that explicitly name that class. Queries that name the class will return only instances of subclasses mapped. For most purposes, the default polymorphisms=IMPLICIT is appropriate. Explicit polymorphisms is useful when two different classes are mapped to the same table This allows a "lightweight" class that contains a subset of the table columns.

  • persister: specifies a custom ClassPersister. The persister attribute lets you customize the persistence strategy used for the class. You can, for example, specify your own subclass of org.hibernate.persister.EntityPersister, or you can even provide a completely new implementation of the interface org.hibernate.persister.ClassPersister that implements, for example, persistence via stored procedure calls, serialization to flat files or LDAP. See org.hibernate.test.CustomPersister for a simple example of "persistence" to a Hashtable.

  • optimisticLock (defaults to VERSION): determines the optimistic locking strategy. If you enable dynamicUpdate, you will have a choice of optimistic locking strategies:

    • version(版本检查):检查 version/timestamp 字段

    • all(全部):检查全部字段

    • dirty(脏检查):只检察修改过的字段,允许某些并行更新

    • none(不检查):不使用乐观锁定

    我们强烈建议你在 Hibernate 中使用 version/timestamp 字段来进行乐观锁定。这个选择可以优化性能,且能够处理对脱管实例的修改(例如:在使用 Session.merge() 的时候)。

提示

Be sure to import @javax.persistence.Entity to mark a class as an entity. It's a common mistake to import @org.hibernate.annotations.Entity by accident.

@Entity

@Subselect("select item.name, max(bid.amount), count(*) "
        + "from item "
        + "join bid on bid.item_id = item.id "
        + "group by item.name")
@Synchronize( {"item", "bid"} ) //tables impacted
public class Summary {
    @Id
    public String getId() { return id; }
    ...
}
<class
        name="(1)ClassName"
        table=(2)"tableName"
        discri(3)minator-value="discriminator_value"
        mutabl(4)e="true|false"
        schema(5)="owner"
        catalo(6)g="catalog"
        proxy=(7)"ProxyInterface"
        dynami(8)c-update="true|false"
        dynami(9)c-insert="true|false"
        select(10)-before-update="true|false"
        polymo(11)rphism="implicit|explicit"
        where=(12)"arbitrary sql where condition"
        persis(13)ter="PersisterClass"
        batch-(14)size="N"
        optimi(15)stic-lock="none|version|dirty|all"
        lazy="(16)true|false"
        entity(17)-name="EntityName"
        check=(18)"arbitrary sql check condition"
        rowid=(19)"rowid"
        subsel(20)ect="SQL expression"
        abstra(21)ct="true|false"
        node="element-name"
/>

1

name(可选):持久化类(或者接口)的 Java 全限定名。 如果这个属性不存在,Hibernate 将假定这是一个非 POJO 的实体映射。

2

table(可选 — 默认是类的非全限定名):对应的数据库表名。

3

discriminator-value(可选 — 默认和类名一样):一个用于区分不同的子类的值,在多态行为时使用。它可以接受的值包括 nullnot null

4

mutable(可选,默认值为 true):表明该类的实例是可变的或者不可变的。

5

schema(可选):覆盖在根 <hibernate-mapping> 元素中指定的 schema 名字。

6

catalog(可选):覆盖在根 <hibernate-mapping> 元素中指定的 catalog 名字。

7

proxy(可选):指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。

8

dynamic-update(可选,默认为 false):指定用于 UPDATE 的 SQL 将会在运行时动态生成,并且只更新那些改变过的字段。

9

dynamic-insert(可选,默认为 false):指定用于 INSERT 的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。

10

select-before-update(可选,默认为 false):指定 Hibernate 除非确定对象真正被修改了(如果该值为 true — 译注),否则不会执行 SQL UPDATE 操作。在特定场合(实际上,它只在一个瞬时对象(transient object)关联到一个新的 session 中时执行的 update() 中生效),这说明 Hibernate 会在 UPDATE 之前执行一次额外的 SQL SELECT 操作来决定是否确实需要执行 UPDATE

11

polymorphisms (optional - defaults to implicit): determines whether implicit or explicit query polymorphisms is used.

12

where(可选)指定一个附加的 SQL WHERE 条件,在抓取这个类的对象时会一直增加这个条件。

13

persister(可选):指定一个定制的 ClassPersister

14

batch-size(可选,默认是 1)指定一个用于 根据标识符(identifier)抓取实例时使用的 "batch size"(批次抓取数量)。

15

optimistic-lock(乐观锁定)(可选,默认是 version):决定乐观锁定的策略。

(16)

lazy(可选):通过设置 lazy="false",所有的延迟加载(Lazy fetching)功能将被全部禁用(disabled)。

(17)

entity-name (optional - defaults to the class name): Hibernate3 allows a class to be mapped multiple times, potentially to different tables. It also allows entity mappings that are represented by Maps or XML at the Java level. In these cases, you should provide an explicit arbitrary name for the entity. See 第 4.4 节 “动态模型(Dynamic models)” and 第 20 章 XML 映射 for more information.

(18)

check(可选):这是一个 SQL 表达式, 用于为自动生成的 schema 添加多行(multi-row)约束检查

(19)

rowid(可选):Hibernate 可以使用数据库支持的所谓的 ROWIDs,例如:Oracle 数据库,如果你设置这个可选的 rowid,Hibernate 可以使用额外的字段 rowid 实现快速更新。ROWID 是这个功能实现的重点,它代表了一个存储元组(tuple)的物理位置。

(20)

subselect(可选):它将一个不可变(immutable)并且只读的实体映射到一个数据库的子查询中。当你想用视图代替一张基本表的时候,这是有用的,但最好不要这样做。更多的介绍请看下面内容。

(21)

abstract(可选):用于在 <union-subclass> 的层次结构(hierarchies)中标识抽象超类。

<class name="Summary">
    <subselect>
        select item.name, max(bid.amount), count(*)
        from item
        join bid on bid.item_id = item.id
        group by item.name
    </subselect>
    <synchronize table="item"/>
    <synchronize table="bid"/>
    <id name="name"/>
    ...
</class>
@Entity

public class Person {
   @Id Integer getId() { ... }
   ...
}
<id
        name="(1)propertyName"
        type="(2)typename"
        column(3)="column_name"
        unsave(4)d-value="null|any|none|undefined|id_value"
        access(5)="field|property|ClassName">
        node="element-name|@attribute-name|element/@attribute|."

        <generator class="generatorClass"/>
</id>

1

name(可选):标识属性的名字。

2

type(可选):一个 Hibernate 类型的名字。

3

column(可选 — 默认为属性名):主键字段的名字。

4

unsaved-value(可选 — 默认为一个切合实际(sensible)的值):一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的 session 中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。

5

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

  • use a component type to represent the identifier and map it as a property in the entity: you then annotated the property as @EmbeddedId. The component type has to be Serializable.

  • map multiple properties as @Id properties: the identifier type is then the entity class itself and needs to be Serializable. This approach is unfortunately not standard and only supported by Hibernate.

  • map multiple properties as @Id properties and declare an external class to be the identifier type. This class, which needs to be Serializable, is declared on the entity via the @IdClass annotation. The identifier type must contain the same properties as the identifier properties of the entity: each property name must be the same, its type must be the same as well if the entity property is of a basic type, its type must be the type of the primary key of the associated entity if the entity property is an association (either a @OneToOne or a @ManyToOne).

@Entity

class User {
   @EmbeddedId
   @AttributeOverride(name="firstName", column=@Column(name="fld_firstname")
   UserId id;
   Integer age;
}
@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;
}
@Entity

class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;
   @MapsId("userId")
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   @OneToOne User user;
}
@Embeddable
class CustomerId implements Serializable {
   UserId userId;
   String customerNumber;
   //implements equals and hashCode
}
@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}
@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;
   //implements equals and hashCode
}

提示

The component type used as identifier must implement equals() and hashCode().

警告

The id value can be copied as late as flush time, don't rely on it until after flush time.

@Entity

class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;
}
@Embeddable
class CustomerId implements Serializable {
   @OneToOne
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   }) 
   User user;
   String customerNumber;
   //implements equals and hashCode
}
@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}
@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;
   //implements equals and hashCode
}
<composite-id
        name="propertyName"
        class="ClassName"
        mapped="true|false"
        access="field|property|ClassName"
        node="element-name|.">

        <key-property name="propertyName" type="typename" column="column_name"/>
        <key-many-to-one name="propertyName" class="ClassName" column="column_name"/>
        ......
</composite-id>
<class name="User">
   <composite-id name="id" class="UserId">
      <key-property name="firstName" column="fld_firstname"/>
      <key-property name="lastName"/>
   </composite-id>
</class>
<class name="Customer">
   <composite-id name="id" class="CustomerId">
      <key-property name="firstName" column="userfirstname_fk"/>
      <key-property name="lastName" column="userfirstname_fk"/>
      <key-property name="customerNumber"/>
   </composite-id>

   <property name="preferredCustomer"/>

   <many-to-one name="user">
      <column name="userfirstname_fk" updatable="false" insertable="false"/>
      <column name="userlastname_fk" updatable="false" insertable="false"/>
   </many-to-one>
</class>

<class name="User">
   <composite-id name="id" class="UserId">
      <key-property name="firstName"/>
      <key-property name="lastName"/>
   </composite-id>

   <property name="age"/>
</class>
  • the order of the properties (and column) matters. It must be the same between the association and the primary key of the associated entity

  • the many to one uses the same columns as the primary key and thus must be marked as read only (insertable and updatable to false).

  • unlike with @MapsId, the id value of the associated entity is not transparently copied, check the foreign id generator for more information.

<class name="Customer">
   <composite-id name="id" class="CustomerId">
      <key-many-to-one name="user">
         <column name="userfirstname_fk"/>
         <column name="userlastname_fk"/>
      </key-many-to-one>
      <key-property name="customerNumber"/>
   </composite-id>

   <property name="preferredCustomer"/>
</class>

<class name="User">
   <composite-id name="id" class="UserId">
      <key-property name="firstName"/>
      <key-property name="lastName"/>
   </composite-id>

   <property name="age"/>
</class>
@Entity

class Customer implements Serializable {
   @Id @OneToOne
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   User user;
  
   @Id String customerNumber;
   boolean preferredCustomer;
   //implements equals and hashCode
}
@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}
@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;
   //implements equals and hashCode
}
<class name="Customer">
   <composite-id>
      <key-many-to-one name="user">
         <column name="userfirstname_fk"/>
         <column name="userlastname_fk"/>
      </key-many-to-one>
      <key-property name="customerNumber"/>
   </composite-id>

   <property name="preferredCustomer"/>
</class>

<class name="User">
   <composite-id name="id" class="UserId">
      <key-property name="firstName"/>
      <key-property name="lastName"/>
   </composite-id>

   <property name="age"/>
</class>

警告

This approach is inherited from the EJB 2 days and we recommend against its use. But, after all it's your application and Hibernate supports it.

@Entity

@IdClass(CustomerId.class)
class Customer implements Serializable {
   @Id @OneToOne
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   }) 
   User user;
  
   @Id String customerNumber;
   boolean preferredCustomer;
}
class CustomerId implements Serializable {
   UserId user;
   String customerNumber;
   //implements equals and hashCode
}
@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
   //implements equals and hashCode
}
@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;
   //implements equals and hashCode
}
@Entity

@IdClass(CustomerId.class)
class Customer implements Serializable {
   @Id @OneToOne
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   }) 
   User user;
  
   @Id String customerNumber;
   boolean preferredCustomer;
}
class CustomerId implements Serializable {
   @OneToOne User user;
   String customerNumber;
   //implements equals and hashCode
}
@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
   //implements equals and hashCode
}
@Embeddable
class UserId implements Serializable {
  String firstName;
  String lastName;
}
<class name="Customer">
   <composite-id class="CustomerId" mapped="true">
      <key-many-to-one name="user">
         <column name="userfirstname_fk"/>
         <column name="userlastname_fk"/>
      </key-many-to-one>
      <key-property name="customerNumber"/>
   </composite-id>

   <property name="preferredCustomer"/>
</class>

<class name="User">
   <composite-id name="id" class="UserId">
      <key-property name="firstName"/>
      <key-property name="lastName"/>
   </composite-id>

   <property name="age"/>
</class>
  • IDENTITY: supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int.

  • SEQUENCE (called seqhilo in Hibernate): uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a named database sequence.

  • TABLE (called MultipleHiLoPerTableGenerator in Hibernate) : uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

  • AUTO: selects IDENTITY, SEQUENCE or TABLE depending upon the capabilities of the underlying database.

重要

We recommend all new projects to use the new enhanced identifier generators. They are deactivated by default for entities using annotations but can be activated using hibernate.id.new_generator_mappings=true. These new generators are more efficient and closer to the JPA 2 specification semantic.

However they are not backward compatible with existing Hibernate based application (if a sequence or a table is used for id generation). See XXXXXXX ??? for more information on how to activate them.

@Entity

public class Customer {
   @Id @GeneratedValue
   Integer getId() { ... };
}
@Entity 
public class Invoice {
   @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
   Integer getId() { ... };
}
  • name: name of the generator

  • table / sequenceName: name of the table or the sequence (defaulting respectively to hibernate_sequences and hibernate_sequence)

  • catalog / schema:

  • initialValue: the value from which the id is to start generating

  • allocationSize: the amount to increment by when allocating id numbers from the generator

  • pkColumnName: the column name containing the entity identifier

  • valueColumnName: the column name containing the identifier value

  • pkColumnValue: the entity identifier

  • uniqueConstraints: any potential column constraint on the table containing the ids

@Id 

@GeneratedValue(
    strategy=GenerationType.SEQUENCE, 
    generator="SEQ_GEN")
@javax.persistence.SequenceGenerator(
    name="SEQ_GEN",
    sequenceName="my_sequence",
    allocationSize=20
)
public Integer getId() { ... }        
<table-generator name="EMP_GEN"

            table="GENERATOR_TABLE"
            pk-column-name="key"
            value-column-name="hi"
            pk-column-value="EMP"
            allocation-size="20"/>
//and the annotation equivalent
@javax.persistence.TableGenerator(
    name="EMP_GEN",
    table="GENERATOR_TABLE",
    pkColumnName = "key",
    valueColumnName = "hi"
    pkColumnValue="EMP",
    allocationSize=20
)
<sequence-generator name="SEQ_GEN" 
    sequence-name="my_sequence"
    allocation-size="20"/>
//and the annotation equivalent
@javax.persistence.SequenceGenerator(
    name="SEQ_GEN",
    sequenceName="my_sequence",
    allocationSize=20
)
         

注意

Package level definition is not supported by the JPA specification. However, you can use the @GenericGenerator at the package level (see ???).

@Id @GeneratedValue(generator="system-uuid")

@GenericGenerator(name="system-uuid", strategy = "uuid")
public String getId() {
@Id @GeneratedValue(generator="trigger-generated")
@GenericGenerator(
    name="trigger-generated", 
    strategy = "select",
    parameters = @Parameter(name="key", value = "socialSecurityNumber")
)
public String getId() {
<id name="id" type="long" column="cat_id">
        <generator class="org.hibernate.id.TableHiLoGenerator">
                <param name="table">uid_table</param>
                <param name="column">next_hi_value_column</param>
        </generator>
</id>
<id name="id" type="long" column="cat_id">
        <generator class="hilo">
                <param name="table">hi_value</param>
                <param name="column">next_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>
<id name="id" type="long" column="cat_id">
        <generator class="seqhilo">
                <param name="sequence">hi_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>
<id name="id" type="long" column="person_id">
        <generator class="sequence">
                <param name="sequence">person_id_sequence</param>
        </generator>
</id>
<id name="id" type="long" column="person_id" unsaved-value="0">
        <generator class="identity"/>
</id>
<id name="id" type="long" column="person_id">
        <generator class="select">
                <param name="key">socialSecurityNumber</param>
        </generator>
</id>
@Entity

class MedicalHistory implements Serializable {
  @Id @OneToOne
  @JoinColumn(name = "person_id")
  Person patient;
}
@Entity
public class Person implements Serializable {
  @Id @GeneratedValue Integer id;
}
@Entity

class MedicalHistory implements Serializable {
  @Id Integer id;
  @MapsId @OneToOne
  @JoinColumn(name = "patient_id")
  Person patient;
}
@Entity
class Person {
  @Id @GeneratedValue Integer id;
}
<class name="MedicalHistory">
   <id name="id">
      <generator class="foreign">
         <param name="property">patient</param>
      </generator>
   </id>
   <one-to-one name="patient" class="Person" constrained="true"/>
</class>
  • sequence_name(可选 — 默认为 hibernate_sequence):序列或表的名字

  • initial_value(可选,默认为 1):从序列/表里获取的初始值。按照序列创建的术语,这等同于子句 "STARTS WITH"。

  • increment_size(可选 - 缺省为 1):对序列/表的调用应该区分的值。按照序列创建的术语,这等同于子句 "INCREMENT BY"。

  • force_table_use(可选 - 缺省为 false):即使方言可能支持序列,是否也应该强制把表用作后台结构。

  • value_column(可选 - 缺省为 next_val):只和表结构相关,它是用于保存值的字段的名称。

  • optimizer (optional - defaults to none): See 第 5.1.2.3.1 节 “标识符生成器的优化”

  • table_name(可选 — 默认是 hibernate_sequences):所用的表的名称。

  • value_column_name(可选 — 默认为 next_val):用于存储这些值的表的字段的名字。

  • segment_column_name(可选,默认为 sequence_name):用于保存 "segment key" 的字段的名称。这是标识使用哪个增量值的值。

  • segment_value(可选,默认为 default):我们为这个生成器获取增量值的 segment 的 "segment key"。

  • segment_value_length(可选 — 默认为 255):用于 schema 生成;创建 Segment Key 字段的字段大小。

  • initial_value(可选 — 默认是 1):从表里获取的初始值。

  • increment_size(可选 — 默认是 1):对表随后的调用应该区分的值。

  • optimizer (optional - defaults to ??): See 第 5.1.2.3.1 节 “标识符生成器的优化”.

  • none(如果没有指定 optimizer,通常这是缺省配置):这不会执行任何优化,在每次请求时都访问数据库。

  • hilo:对从数据库获取的值应用 hi/lo 算法。用于这个 optimizer 的从数据库获取的值应该是有序的。它们表明“组编号”。increment_size 将乘以内存里的值来定义组的“hi 值”。

  • pooled:和 hilo 一样,这个 optimizer 试图最小化对数据库的访问。然而,我们只是简单地把“下一组”的起始值而不是把序列值和分组算法的组合存入到数据库结构里。在这里,increment_size 表示数据库里的值。

警告

The Hibernate team has always felt such a construct as fundamentally wrong. Try hard to fix your data model before using this feature.

@Entity

public class CustomerInventory implements Serializable {
  @Id
  @TableGenerator(name = "inventory",
    table = "U_SEQUENCES",
    pkColumnName = "S_ID",
    valueColumnName = "S_NEXTNUM",
    pkColumnValue = "inventory",
    allocationSize = 1000)
  @GeneratedValue(strategy = GenerationType.TABLE, generator = "inventory")
  Integer id;
  @Id @ManyToOne(cascade = CascadeType.MERGE)
  Customer customer;
}
@Entity
public class Customer implements Serializable {
   @Id
   private int id;
}
@Entity

public class Flight implements Serializable {
...
    @Version
    @Column(name="OPTLOCK")
    public Integer getVersion() { ... }
}           
<version
        column(1)="version_column"
        name="(2)propertyName"
        type="(3)typename"
        access(4)="field|property|ClassName"
        unsave(5)d-value="null|negative|undefined"
        genera(6)ted="never|always"
        insert(7)="true|false"
        node="element-name|@attribute-name|element/@attribute|."
/>

1

column(可选 — 默认为属性名):指定持有版本号的字段名。

2

name:持久化类的属性名。

3

type(可选 — 默认是 integer):版本号的类型。

4

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

5

unsaved-value(可选 — 默认是 undefined):用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况 和已经在先前的 session 中保存或装载的脱管(detached)实例区分开来。(undefined 指明应被使用的标识属性值。)

6

generated(可选 — 默认是 never):表明此版本属性值是否实际上是由数据库生成的。请参阅 generated properties 部分的讨论。

7

insert(可选 — 默认是 true):表明此版本列应该包含在 SQL 插入语句中。只有当数据库字段有默认值 0 的时候,才可以设置为 false

@Entity

public class Flight implements Serializable {
...
    @Version
    public Date getLastUpdate() { ... }
}           
<timestamp
        column(1)="timestamp_column"
        name="(2)propertyName"
        access(3)="field|property|ClassName"
        unsave(4)d-value="null|undefined"
        source(5)="vm|db"
        genera(6)ted="never|always"
        node="element-name|@attribute-name|element/@attribute|."
/>

1

column(可选 — 默认为属性名):存有时间戳的字段名。

2

name:在持久化类中的 JavaBeans 风格的属性名,其 Java 类型是 Date 或者 Timestamp 的。

3

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

4

unsaved-value(可选 — 默认是 null):用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的 session 中保存或装载的脱管(detached)实例区分开来。(undefined 指明使用标识属性值进行这种判断。)

5

source(可选 — 默认是 vm):Hibernate 如何才能获取到时间戳的值呢?从数据库,还是当前 JVM?从数据库获取会带来一些负担,因为 Hibernate 必须访问数据库来获得“下一个值”,但是在集群环境中会更安全些。还要注意,并不是所有的 Dialect(方言)都支持获得数据库的当前时间戳的,而支持的数据库中又有一部分因为精度不足,用于锁定是不安全的(例如 Oracle 8)。

6

generated(可选 - 默认是 never):指出时间戳值是否实际上是由数据库生成的。请参阅 generated properties 的讨论。

注意

注意,<timestamp><version type="timestamp"> 是等价的。并且 <timestamp source="db"><version type="dbtimestamp"> 是等价的。

public transient int counter; //transient property


private String firstname; //persistent property
@Transient
String getLengthInMeter() { ... } //transient property
String getName() {... } // persistent property
@Basic
int getLength() { ... } // persistent property
@Basic(fetch = FetchType.LAZY)
String getDetailedComment() { ... } // persistent property
@Temporal(TemporalType.TIME)
java.util.Date getDepartureTime() { ... } // persistent property           
@Enumerated(EnumType.STRING)
Starred getNote() { ... } //enum persisted as String in database
@Lob

public String getFullText() {
    return fullText;
}
@Lob
public byte[] getFullCode() {
    return fullCode;
}
  1. Hibernate 基本类型名(比如:integer, string, character,date, timestamp, float, binary, serializable, object, blob)。

  2. 一个 Java 类的名字,这个类属于一种默认基础类型(比如:int, float,char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob)。

  3. 一个可以序列化的 Java 类的名字。

  4. 一个自定义类型的类的名字。(比如:com.illflow.type.MyCustomType)。

注意

Package level annotations are placed in a file named package-info.java in the appropriate package. Place your annotations before the package declaration.

@TypeDef(

   name = "phoneNumber",
   defaultForType = PhoneNumber.class,
   typeClass = PhoneNumberType.class
)
@Entity
public class ContactDetails {
   [...]
   private PhoneNumber localPhoneNumber;
   @Type(type="phoneNumber")
   private OverseasPhoneNumber overseasPhoneNumber;
   [...]
}
//in org/hibernate/test/annotations/entity/package-info.java

@TypeDefs(
    {
    @TypeDef(
        name="caster",
        typeClass = CasterStringType.class,
        parameters = {
            @Parameter(name="cast", value="lower")
        }
    )
    }
)
package org.hibernate.test.annotations.entity;
//in org/hibernate/test/annotations/entity/Forest.java
public class Forest {
    @Type(type="caster")
    public String getSmallText() {
    ...
}      
@Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")

@Columns(columns = {
    @Column(name="r_amount"),
    @Column(name="r_currency")
})
public MonetaryAmount getAmount() {
    return amount;
}
public class MonetaryAmount implements Serializable {
    private BigDecimal amount;
    private Currency currency;
    ...
}

注意

The placement of annotations within a class hierarchy has to be consistent (either field or on property) to be able to determine the default access type. It is recommended to stick to one single annotation placement strategy throughout your whole application.

  • force the access type of the entity hierarchy

  • override the access type of a specific entity in the class hierarchy

  • override the access type of an embeddable type

@Entity

public class Order {
   @Id private Long id;
   public Long getId() { return id; }
   public void setId(Long id) { this.id = id; }
   @Embedded private Address address;
   public Address getAddress() { return address; }
   public void setAddress() { this.address = address; }
}
@Entity
public class User {
   private Long id;
   @Id public Long getId() { return id; }
   public void setId(Long id) { this.id = id; }
   private Address address;
   @Embedded public Address getAddress() { return address; }
   public void setAddress() { this.address = address; }
}
@Embeddable
@Access(AcessType.PROPERTY)
public class Address {
   private String street1;
   public String getStreet1() { return street1; }
   public void setStreet1() { this.street1 = street1; }
   private hashCode; //not persistent
}
@Entity

public class Order {
   @Id private Long id;
   public Long getId() { return id; }
   public void setId(Long id) { this.id = id; }
   @Transient private String userId;
   @Transient private String orderId;
   @Access(AccessType.PROPERTY)
   public String getOrderNumber() { return userId + ":" + orderId; }
   public void setOrderNumber() { this.userId = ...; this.orderId = ...; }
}

@org.hibernate.annotations.AccessType

The annotation @org.hibernate.annotations.AccessType should be considered deprecated for FIELD and PROPERTY access. It is still useful however if you need to use a custom access type.

  • not annotated at all

  • annotated with @Basic

  • annotated with @Version

  • annotated with @Lob

  • annotated with @Temporal

@Entity

public class Flight implements Serializable {
...
@Column(updatable = false, name = "flight_name", nullable = false, length=50)
public String getName() { ... }
            
@Column(
    name="colu(1)mnName";
    boolean un(2)ique() default false;
    boolean nu(3)llable() default true;
    boolean in(4)sertable() default true;
    boolean up(5)datable() default true;
    String col(6)umnDefinition() default "";
    String tab(7)le() default "";
    int length(8)() default 255;
    int precis(9)ion() default 0; // decimal precision
    int scale((10)) default 0; // decimal scale

1

name (optional): the column name (default to the property name)

2

unique (optional): set a unique constraint on this column or not (default false)

3

nullable (optional): set the column as nullable (default true).

4

insertable (optional): whether or not the column will be part of the insert statement (default true)

5

updatable (optional): whether or not the column will be part of the update statement (default true)

6

columnDefinition (optional): override the sql DDL fragment for this particular column (non portable)

7

table (optional): define the targeted table (default primary table)

8

length (optional): column length (default 255)

8

precision (optional): column decimal precision (default 0)

10

scale (optional): column decimal scale if useful (default 0)

@Formula("obj_length * obj_height * obj_width")

public long getObjectVolume()
  • If the property is of a single type, it is mapped as @Basic

  • Otherwise, if the type of the property is annotated as @Embeddable, it is mapped as @Embedded

  • Otherwise, if the type of the property is Serializable, it is mapped as @Basic in a column holding the object in its serialized version

  • Otherwise, if the type of the property is java.sql.Clob or java.sql.Blob, it is mapped as @Lob with the appropriate LobType

<property
        name="(1)propertyName"
        column(2)="column_name"
        type="(3)typename"
        update(4)="true|false"
        insert(4)="true|false"
        formul(5)a="arbitrary SQL expression"
        access(6)="field|property|ClassName"
        lazy="(7)true|false"
        unique(8)="true|false"
        not-nu(9)ll="true|false"
        optimi(10)stic-lock="true|false"
        genera(11)ted="never|insert|always"
        node="element-name|@attribute-name|element/@attribute|."
        index="index_name"
        unique_key="unique_key_id"
        length="L"
        precision="P"
        scale="S"
/>

1

name:属性的名字,以小写字母开头。

2

column(可选 — 默认为属性名字):对应的数据库字段名。 也可以通过嵌套的 <column> 元素指定。

3

type(可选):一个 Hibernate 类型的名字。

4

update, insert(可选 — 默认为 true): 表明用于 UPDATE 和/或 INSERT 的 SQL 语句中是否包含这个被映射了的字段。这二者如果都设置为 false 则表明这是一个“外源性(derived)”的属性,它的值来源于映射到同一个(或多个) 字段的某些其他属性,或者通过一个 trigger(触发器)或其他程序生成。

5

formula(可选):一个 SQL 表达式,定义了这个计算 (computed) 属性的值。计算属性没有和它对应的数据库字段。

6

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

7

lazy(可选 — 默认为 false):指定 指定实例变量第一次被访问时,这个属性是否延迟抓取(fetched lazily)( 需要运行时字节码增强)。

8

unique(可选):使用 DDL 为该字段添加唯一的约束。同样,允许它作为 property-ref 引用的目标。

9

not-null(可选):使用 DDL 为该字段添加可否为空(nullability)的约束。

10

optimistic-lock(可选 — 默认为 true):指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。

11

generated(可选 — 默认为 never):表明此属性值是否实际上是由数据库生成的。请参阅 generated properties 的讨论。

  1. Hibernate 基本类型名(比如:integer, string, character,date, timestamp, float, binary, serializable, object, blob)。

  2. 一个 Java 类的名字,这个类属于一种默认基础类型(比如:int, float,char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob)。

  3. 一个可以序列化的 Java 类的名字。

  4. 一个自定义类型的类的名字。(比如:com.illflow.type.MyCustomType)。

<property name="totalPrice"
    formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
                WHERE li.productId = p.productId
                AND li.customerId = customerId
                AND li.orderNumber = orderNumber )"/>
@Entity

public class Person implements Serializable {
    // Persistent component using defaults
    Address homeAddress;
    @Embedded
    @AttributeOverrides( {
            @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),
            @AttributeOverride(name="name", column = @Column(name="bornCountryName") )
    } )
    Country bornIn;
    ...
}          
@Embeddable

public class Address implements Serializable {
    String city;
    Country nationality; //no overriding here
}            
@Embeddable

public class Country implements Serializable {
    private String iso2;
    @Column(name="countryName") private String name;
    public String getIso2() { return iso2; }
    public void setIso2(String iso2) { this.iso2 = iso2; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    ...
}            
@Embedded

    @AttributeOverrides( {
            @AttributeOverride(name="city", column = @Column(name="fld_city") ),
            @AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2") ),
            @AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName") )
            //nationality columns in homeAddress are overridden
    } )
    Address homeAddress;
<component
        name="(1)propertyName"
        class=(2)"className"
        insert(3)="true|false"
        update(4)="true|false"
        access(5)="field|property|ClassName"
        lazy="(6)true|false"
        optimi(7)stic-lock="true|false"
        unique(8)="true|false"
        node="element-name|."
>

        <property ...../>
        <many-to-one .... />
        ........
</component>

1

name:属性名。

2

class(可选 — 默认为通过反射得到的属性类型):组件(子)类的名字。

3

insert:被映射的字段是否出现在 SQL 的 INSERT 语句中?

4

update:被映射的字段是否出现在 SQL 的 UPDATE 语句中?

5

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

6

lazy(可选 — 默认是 false):表明此组件应在实例变量第一次被访问的时候延迟加载(需要编译时字节码装置器)。

7

optimistic-lock(可选 — 默认是 true):表明更新此组件是否需要获取乐观锁。换句话说,当这个属性变脏时,是否增加版本号(Version)。

8

unique(可选 — 默认是 false):表明组件映射的所有字段上都有唯一性约束。

  • Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy

  • Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses

  • Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="planetype",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue("Plane")
public class Plane { ... }
@Entity
@DiscriminatorValue("A320")
public class A320 extends Plane { ... }          
<subclass
        name="(1)ClassName"
        discri(2)minator-value="discriminator_value"
        proxy=(3)"ProxyInterface"
        lazy="(4)true|false"
        dynamic-update="true|false"
        dynamic-insert="true|false"
        entity-name="EntityName"
        node="element-name"
        extends="SuperclassName">

        <property .... />
        .....
</subclass>

1

name:子类的全限定名。

2

discriminator-value(辨别标志)(可选 — 默认为类名):一个用于区分每个独立的子类的值。

3

proxy(可选):指定一个类或者接口,在延迟装载时作为代理使用。

4

lazy(可选,默认是 true):设置为 lazy="false" 禁止使用延迟装载。

注意

The enum DiscriminatorType used in javax.persitence.DiscriminatorColumn only contains the values STRING, CHAR and INTEGER which means that not all Hibernate supported types are available via the @DiscriminatorColumn annotation.

提示

There is also a @org.hibernate.annotations.ForceDiscriminator annotation which is deprecated since version 3.6. Use @DiscriminatorOptions instead.

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="planetype",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue("Plane")
public class Plane { ... }
@Entity
@DiscriminatorValue("A320")
public class A320 extends Plane { ... }          
<discriminator
        column(1)="discriminator_column"
        type="(2)discriminator_type"
        force=(3)"true|false"
        insert(4)="true|false"
        formul(5)a="arbitrary sql expression"
/>

1

column(可选 — 默认为 class)discriminator 器字段的名字。

2

type(可选 — 默认为 string)一个 Hibernate 字段类型的名字

3

force(强制)(可选 — 默认为 false)"强制" Hibernate 指定允许的鉴别器值,即使当取得的所有实例都是根类的。

4

insert(可选 - 默认为true)如果你的鉴别器字段也是映射为复合标识(composite identifier)的一部分,则需将这个值设为 false。(告诉 Hibernate 在做 SQL INSERT 时不包含该列)

5

formula(可选)一个 SQL 表达式,在类型判断(判断是父类还是具体子类 — 译注)时执行。可用于基于内容的鉴别器。

<discriminator
    formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
    type="integer"/>
@Entity @Table(name="CATS")

@Inheritance(strategy=InheritanceType.JOINED)
public class Cat implements Serializable { 
    @Id @GeneratedValue(generator="cat-uuid") 
    @GenericGenerator(name="cat-uuid", strategy="uuid")
    String getId() { return id; }
    ...
}
@Entity @Table(name="DOMESTIC_CATS")
@PrimaryKeyJoinColumn(name="CAT")
public class DomesticCat extends Cat { 
    public String getName() { return name; }
}            

注意

The table name still defaults to the non qualified class name. Also if @PrimaryKeyJoinColumn is not set, the primary key / foreign key columns are assumed to have the same names as the primary key columns of the primary table of the superclass.

<joined-subclass
        name="(1)ClassName"
        table=(2)"tablename"
        proxy=(3)"ProxyInterface"
        lazy="(4)true|false"
        dynamic-update="true|false"
        dynamic-insert="true|false"
        schema="schema"
        catalog="catalog"
        extends="SuperclassName"
        persister="ClassName"
        subselect="SQL expression"
        entity-name="EntityName"
        node="element-name">

        <key .... >

        <property .... />
        .....
</joined-subclass>

1

name:子类的全限定名。

2

table:子类的表名。

3

proxy(可选):指定一个类或者接口,在延迟装载时作为代理使用。

4

lazy(可选,默认是 true):设置为 lazy="false" 禁止使用延迟装载。

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

<hibernate-mapping package="eg">

        <class name="Cat" table="CATS">
                <id name="id" column="uid" type="long">
                        <generator class="hilo"/>
                </id>
                <property name="birthdate" type="date"/>
                <property name="color" not-null="true"/>
                <property name="sex" not-null="true"/>
                <property name="weight"/>
                <many-to-one name="mate"/>
                <set name="kittens">
                        <key column="MOTHER"/>
                        <one-to-many class="Cat"/>
                </set>
                <joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
                    <key column="CAT"/>
                    <property name="name" type="string"/>
                </joined-subclass>
        </class>

        <class name="eg.Dog">
                <!-- mapping for Dog could go here -->
        </class>

</hibernate-mapping>
@Entity

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Flight implements Serializable { ... }            
<union-subclass
        name="(1)ClassName"
        table=(2)"tablename"
        proxy=(3)"ProxyInterface"
        lazy="(4)true|false"
        dynamic-update="true|false"
        dynamic-insert="true|false"
        schema="schema"
        catalog="catalog"
        extends="SuperclassName"
        abstract="true|false"
        persister="ClassName"
        subselect="SQL expression"
        entity-name="EntityName"
        node="element-name">

        <property .... />
        .....
</union-subclass>

1

name:子类的全限定名。

2

table:子类的表名。

3

proxy(可选):指定一个类或者接口,在延迟装载时作为代理使用。

4

lazy(可选,默认是 true):设置为 lazy="false" 禁止使用延迟装载。

@MappedSuperclass

public class BaseEntity {
    @Basic
    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastUpdate() { ... }
    public String getLastUpdater() { ... }
    ...
}
@Entity class Order extends BaseEntity {
    @Id public Integer getId() { ... }
    ...
}

注意

Properties from superclasses not mapped as @MappedSuperclass are ignored.

注意

The default access type (field or methods) is used, unless you use the @Access annotation.

注意

The same notion can be applied to @Embeddable objects to persist properties from their superclasses. You also need to use @MappedSuperclass to do that (this should not be considered as a standard EJB3 feature though)

注意

It is allowed to mark a class as @MappedSuperclass in the middle of the mapped inheritance hierarchy.

注意

Any class in the hierarchy non annotated with @MappedSuperclass nor @Entity will be ignored.

@MappedSuperclass

public class FlyingObject implements Serializable {
    public int getAltitude() {
        return altitude;
    }
    @Transient
    public int getMetricAltitude() {
        return metricAltitude;
    }
    @ManyToOne
    public PropulsionType getPropulsion() {
        return metricAltitude;
    }
    ...
}
@Entity
@AttributeOverride( name="altitude", column = @Column(name="fld_altitude") )
@AssociationOverride( 
   name="propulsion", 
   joinColumns = @JoinColumn(name="fld_propulsion_fk") 
)
public class Plane extends FlyingObject {
    ...
}
@Entity

@Table(name="MainCat")
@SecondaryTables({
    @SecondaryTable(name="Cat1", pkJoinColumns={
        @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")
    ),
    @SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})})
})
public class Cat implements Serializable {
    private Integer id;
    private String name;
    private String storyPart1;
    private String storyPart2;
    @Id @GeneratedValue
    public Integer getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    
    @Column(table="Cat1")
    public String getStoryPart1() {
        return storyPart1;
    }
    @Column(table="Cat2")
    public String getStoryPart2() {
        return storyPart2;
    }
}
  • fetch: If set to JOIN, the default, Hibernate will use an inner join to retrieve a secondary table defined by a class or its superclasses and an outer join for a secondary table defined by a subclass. If set to SELECT then Hibernate will use a sequential select for a secondary table defined on a subclass, which will be issued only if a row turns out to represent an instance of the subclass. Inner joins will still be used to retrieve a secondary defined by the class and its superclasses.

  • inverse: If true, Hibernate will not try to insert or update the properties defined by this join. Default to false.

  • optional: If enabled (the default), Hibernate will insert a row only if the properties defined by this join are non-null and will always use an outer join to retrieve the properties.

  • foreignKey: defines the Foreign Key name of a secondary table pointing back to the primary table.

@Entity

@Table(name="MainCat")
@SecondaryTable(name="Cat1")
@org.hibernate.annotations.Table(
   appliesTo="Cat1",
   fetch=FetchMode.SELECT,
   optional=true)
public class Cat implements Serializable {
    private Integer id;
    private String name;
    private String storyPart1;
    private String storyPart2;
    @Id @GeneratedValue
    public Integer getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    
    @Column(table="Cat1")
    public String getStoryPart1() {
        return storyPart1;
    }
    @Column(table="Cat2")
    public String getStoryPart2() {
        return storyPart2;
    }
}
<join
        table=(1)"tablename"
        schema(2)="owner"
        catalo(3)g="catalog"
        fetch=(4)"join|select"
        invers(5)e="true|false"
        option(6)al="true|false">

        <key ... />

        <property ... />
        ...
</join>

1

table:被连接表的名称。

2

schema(可选):覆盖在根 <hibernate-mapping> 元素中指定的 schema 名字。

3

catalog(可选):覆盖在根 <hibernate-mapping> 元素中指定的 catalog 名字。

4

fetch(可选 — 默认是 join):如果设置为默认值 join,Hibernate 将使用一个内连接来得到这个类或其超类定义的 <join>,而使用一个外连接来得到其子类定义的 <join>。如果设置为 select,则 Hibernate 将为子类定义的 <join> 使用顺序选择。这仅在一行数据表示一个子类的对象的时候才会发生。对这个类和其超类定义的 <join>,依然会使用内连接得到。

5

inverse(可选 — 默认是 false):如果打开,Hibernate 不会插入或者更新此连接定义的属性。

6

optional(可选 — 默认是 false):如果打开,Hibernate 只会在此连接定义的属性非空时插入一行数据,并且总是使用一个外连接来得到这些属性。

<class name="Person"
    table="PERSON">

    <id name="id" column="PERSON_ID">...</id>

    <join table="ADDRESS">
        <key column="ADDRESS_ID"/>
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </join>
    ...
  1. basic operations, which include: persist, merge, delete, save-update, evict, replicate, lock and refresh;

  2. special values: delete-orphan or all ;

  3. comma-separated combinations of operation names: cascade="persist,merge,evict" or cascade="all,delete-orphan". See 第 11.11 节 “传播性持久化(transitive persistence)” for a full explanation. Note that single valued many-to-one associations do not support orphan delete.

  • @ManyToOne if several entities can point to the the target entity

  • @OneToOne if only a single entity can point to the the target entity

@Entity

public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
        return company;
    }
    ...
}            
@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 {
    ...
}
@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;
    }
    ...
}       

注意

You can use a SQL fragment to simulate a physical join column using the @JoinColumnOrFormula / @JoinColumnOrformulas annotations (just like you can use a SQL fragment to simulate a property column via the @Formula annotation).

@Entity

public class Ticket implements Serializable {
    @ManyToOne
    @JoinColumnOrFormula(formula="(firstname + ' ' + lastname)")
    public Person getOwner() {
        return person;
    }
    ...
}       
@Entity

public class Child {
    ...
    @ManyToOne
    @NotFound(action=NotFoundAction.IGNORE)
    public Parent getParent() { ... }
    ...
}

@Entity

public class Child {
    ...
    @ManyToOne
    @OnDelete(action=OnDeleteAction.CASCADE)
    public Parent getParent() { ... }
    ...
}

@Entity

public class Child {
    ...
    @ManyToOne
    @ForeignKey(name="FK_PARENT")
    public Parent getParent() { ... }
    ...
}
alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent

@Entity

class Person {
   @Id Integer personNumber;
   String firstName;
   @Column(name="I")
   String initial;
   String lastName;
}
@Entity
class Home {
   @ManyToOne
   @JoinColumns({
      @JoinColumn(name="first_name", referencedColumnName="firstName"),
      @JoinColumn(name="init", referencedColumnName="I"),
      @JoinColumn(name="last_name", referencedColumnName="lastName"),
   })
   Person owner
}
<many-to-one
        name="(1)propertyName"
        column(2)="column_name"
        class=(3)"ClassName"
        cascad(4)e="cascade_style"
        fetch=(5)"join|select"
        update(6)="true|false"
        insert(6)="true|false"
        proper(7)ty-ref="propertyNameFromAssociatedClass"
        access(8)="field|property|ClassName"
        unique(9)="true|false"
        not-nu(10)ll="true|false"
        optimi(11)stic-lock="true|false"
        lazy="(12)proxy|no-proxy|false"
        not-fo(13)und="ignore|exception"
        entity(14)-name="EntityName"
        formul(15)a="arbitrary SQL expression"
        node="element-name|@attribute-name|element/@attribute|."
        embed-xml="true|false"
        index="index_name"
        unique_key="unique_key_id"
        foreign-key="foreign_key_name"
/>

1

name:属性名。

2

column(可选):外键字段的名称。也可以通过嵌套的 <column> 指定。

3

class(可选 — 默认是通过反射得到的属性类型):被关联的类的名字。

4

cascade(级联)(可选)表明操作是否从父对象级联到被关联的对象。

5

fetch(可选 — 默认为 select):在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。

6

update, insert(可选 — 默认为 true)指定对应的字段是否包含在用于 UPDATE 和/或 INSERT 的 SQL 语句中。如果二者都是false,则这是一个纯粹的 “外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他属性得到 或者通过 trigger(触发器)、或其他程序生成。

7

property-ref:(可选)被关联到此外键的类中的对应属性的名字。如果没有指定,被关联类的主键将被使用。

8

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

9

unique(可选):使用 DDL 为外键字段生成一个唯一约束。此外, 这也可以用作 property-ref 的目标属性。这使关联同时具有一对一的效果。

10

not-null(可选):使用 DDL 为外键字段生成一个非空约束。

11

optimistic-lock(可选 — 默认为 true):指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。

12

lazy(可选 — 默认为 proxy):默认情况下,单点关联是经过代理的。lazy="no-proxy" 指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。lazy="false" 指定此关联总是被预先抓取。

13

not-found(可选 - 默认为exception):指定如何处理引用缺失行的外键:ignore 会把缺失的行作为一个空关联处理。

14

entity-name(可选):被关联的类的实体名。

15

formula(可选):SQL 表达式,用于定义 computed(计算出的)外键值。

<many-to-one name="product" class="Product" column="PRODUCT_ID"/>
<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>
<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>
<many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/>
@Entity

public class Body {
    @Id
    public Long getId() { return id; }
    @OneToOne(cascade = CascadeType.ALL)
    @MapsId
    public Heart getHeart() {
        return heart;
    }
    ...
}   
@Entity
public class Heart {
    @Id
    public Long getId() { ...}
}           

注意

Many people got confused by these primary key based one to one associations. They can only be lazily loaded if Hibernate knows that the other side of the association is always present. To indicate to Hibernate that it is the case, use @OneToOne(optional=false).

<one-to-one
        name="(1)propertyName"
        class=(2)"ClassName"
        cascad(3)e="cascade_style"
        constr(4)ained="true|false"
        fetch=(5)"join|select"
        proper(6)ty-ref="propertyNameFromAssociatedClass"
        access(7)="field|property|ClassName"
        formul(8)a="any SQL expression"
        lazy="(9)proxy|no-proxy|false"
        entity(10)-name="EntityName"
        node="element-name|@attribute-name|element/@attribute|."
        embed-xml="true|false"
        foreign-key="foreign_key_name"
/>

1

name:属性名。

2

class(可选 — 默认是通过反射得到的属性类型):被关联的类的名字。

3

cascade(级联)(可选)表明操作是否从父对象级联到被关联的对象。

4

constrained(约束)(可选)表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响 save()delete() 在级联执行时的先后顺序以及决定该关联能否被委托(也在 schema export tool 中被使用)。

5

fetch(可选 — 默认为 select):在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。

6

property-ref:(可选)指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键。

7

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

8

formula (可选):绝大多数一对一的关联都指向其实体的主键。在一些少见的情况中,你可能会指向其他的一个或多个字段,或者是一个表达式,这些情况下,你可以用一个 SQL 公式来表示。(可以在 org.hibernate.test.onetooneformula 找到例子)

9

lazy(可选 — 默认为 proxy):默认情况下,单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate会采取预先抓取

10

entity-name(可选):被关联的类的实体名。

<one-to-one name="person" class="Person"/>
<one-to-one name="employee" class="Employee" constrained="true"/>
<class name="person" table="PERSON">
    <id name="id" column="PERSON_ID">
        <generator class="foreign">
            <param name="property">employee</param>
        </generator>
    </id>
    ...
    <one-to-one name="employee"
        class="Employee"
        constrained="true"/>
</class>
@Entity

public class Citizen {
    @Id
    @GeneratedValue
    private Integer id;
    private String firstname;
    private String lastname;
    
    @NaturalId
    @ManyToOne
    private State state;
    @NaturalId
    private String ssn;
    ...
}
//and later on query
List results = s.createCriteria( Citizen.class )
                .add( Restrictions.naturalId().set( "ssn", "1234" ).set( "state", ste ) )
                .list();
<natural-id mutable="true|false"/>
        <property ... />
        <many-to-one ... />
        ......
</natural-id>
  • mutable(可选,默认为 false):默认情况下,自然标识属性被假定为不可变的(常量)。

@Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )

@AnyMetaDef( 
    idType = "integer", 
    metaType = "string", 
    metaValues = {
        @MetaValue( value = "S", targetEntity = StringProperty.class ),
        @MetaValue( value = "I", targetEntity = IntegerProperty.class )
    } )
@JoinColumn( name = "property_id" )
public Property getMainProperty() {
    return mainProperty;
}
//on a package

@AnyMetaDef( name="property" 
    idType = "integer", 
    metaType = "string", 
    metaValues = {
        @MetaValue( value = "S", targetEntity = StringProperty.class ),
        @MetaValue( value = "I", targetEntity = IntegerProperty.class )
    } )
package org.hibernate.test.annotations.any;
//in a class
    @Any( metaDef="property", metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )
    @JoinColumn( name = "property_id" )
    public Property getMainProperty() {
        return mainProperty;
    }
<any name="being" id-type="long" meta-type="string">
    <meta-value value="TBL_ANIMAL" class="Animal"/>
    <meta-value value="TBL_HUMAN" class="Human"/>
    <meta-value value="TBL_ALIEN" class="Alien"/>
    <column name="table_name"/>
    <column name="id"/>
</any>

注意

You cannot mutualize the metadata in hbm.xml as you can in annotations.

<any
        name="(1)propertyName"
        id-typ(2)e="idtypename"
        meta-t(3)ype="metatypename"
        cascad(4)e="cascade_style"
        access(5)="field|property|ClassName"
        optimi(6)stic-lock="true|false"
>
        <meta-value ... />
        <meta-value ... />
        .....
        <column .... />
        <column .... />
        .....
</any>

1

name:属性名

2

id-type:标识符类型

3

meta-type(可选 -默认是 string):允许辨别标志(discriminator)映射的任何类型。

4

cascade(可选 — 默认是none):级联的类型。

5

access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。

6

optimistic-lock(可选 — 默认是 true):表明更新此组件是否需要获取乐观锁。换句话说,当这个属性变脏时,是否增加版本号(Version)。

<properties
        name="(1)logicalName"
        insert(2)="true|false"
        update(3)="true|false"
        optimi(4)stic-lock="true|false"
        unique(5)="true|false"
>

        <property ...../>
        <many-to-one .... />
        ........
</properties>

1

name:分组的逻辑名称 — 不是 实际属性的名称。

2

insert:被映射的字段是否出现在 SQL 的 INSERT 语句中?

3

update:被映射的字段是否出现在 SQL 的 UPDATE 语句中?

4

optimistic-lock(可选 — 默认是 true):表明更新此组件是否需要获取乐观锁。换句话说,当这个属性变脏时,是否增加版本号(Version)。

5

unique(可选 — 默认是 false):表明组件映射的所有字段上都有唯一性约束。

<class name="Person">
    <id name="personNumber"/>

    ...
    <properties name="name"
            unique="true" update="false">
        <property name="firstName"/>
        <property name="initial"/>
        <property name="lastName"/>
    </properties>
</class>
<many-to-one name="owner"
         class="Person" property-ref="name">
    <column name="firstName"/>
    <column name="initial"/>
    <column name="lastName"/>
</many-to-one>

注意

When using annotations as a mapping strategy, such construct is not necessary as the binding between a column and its related column on the associated table is done directly

@Entity

class Person {
   @Id Integer personNumber;
   String firstName;
   @Column(name="I")
   String initial;
   String lastName;
}
@Entity
class Home {
   @ManyToOne
   @JoinColumns({
      @JoinColumn(name="first_name", referencedColumnName="firstName"),
      @JoinColumn(name="init", referencedColumnName="I"),
      @JoinColumn(name="last_name", referencedColumnName="lastName"),
   })
   Person owner
}
  • a hibernate namespace is recognized whenever the resolver encounters a systemId starting with http://www.hibernate.org/dtd/. The resolver attempts to resolve these entities via the classloader which loaded the Hibernate classes.

  • 若 resolver 遇到了一个使用 classpath:// URL 协议的 systemId,它会辨认出这是 user namespace,resolver 试图通过(1) 当前线程上下文的 classloader 和(2) 加载 Hibernate class 的 classloader 来查找这些实体。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [
    <!ENTITY types SYSTEM "classpath://your/domain/types.xml">
]>

<hibernate-mapping package="your.domain">
    <class name="MyEntity">
        <id name="id" type="my-custom-id-type">
            ...
        </id>
    <class>
    &types;
</hibernate-mapping>

<hibernate-mapping
         schem(1)a="schemaName"
         catal(2)og="catalogName"
         defau(3)lt-cascade="cascade_style"
         defau(4)lt-access="field|property|ClassName"
         defau(5)lt-lazy="true|false"
         auto-(6)import="true|false"
         packa(7)ge="package.name"
 />

1

schema(可选):数据库 schema 的名称。

2

catalog(可选):数据库 catalog 的名称。

3

default-cascade(可选 — 默认为 none):默认的级联风格。

4

default-access(可选 — 默认为 property):Hibernate 用来访问所有属性的策略。可以通过实现 PropertyAccessor 接口自定义。

5

default-lazy(可选 — 默认为 true):指定了未明确注明 lazy 属性的 Java 属性和集合类,Hibernate 会采取什么样的默认加载风格。

6

auto-import(可选 — 默认为 true):指定我们是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。

7

package(可选):指定一个包前缀,如果在映射文档中没有指定全限定的类名,就使用这个作为包名。

<key
        column(1)="columnname"
        on-del(2)ete="noaction|cascade"
        proper(3)ty-ref="propertyName"
        not-nu(4)ll="true|false"
        update(5)="true|false"
        unique(6)="true|false"
/>

1

column(可选):外键字段的名称。也可以通过嵌套的 <column> 指定。

2

on-delete(可选,默认是 noaction):表明外键关联是否打开数据库级别的级联删除。

3

property-ref(可选):表明外键引用的字段不是原表的主键(提供给遗留数据)。

4

not-null(可选):表明外键的字段不可为空(这意味着无论何时外键都是主键的一部分)。

5

update(可选):表明外键决不应该被更新(这意味着无论何时外键都是主键的一部分)。

6

unique(可选):表明外键应有唯一性约束(这意味着无论何时外键都是主键的一部分)。

<import class="java.lang.Object" rename="Universe"/>
<import
        class=(1)"ClassName"
        rename(2)="ShortName"
/>

1

class:任何 Java 类的全限定名。

2

rename(可选 — 默认为类的全限定名):在查询语句中可以使用的名字。

注意

This feature is unique to hbm.xml and is not supported in annotations.

<column
        name="column_name"
        length="N"
        precision="N"
        scale="N"
        not-null="true|false"
        unique="true|false"
        unique-key="multicolumn_unique_key_name"
        index="index_name"
        sql-type="sql_type_name"
        check="SQL expression"
        default="SQL expression"
        read="SQL expression"
        write="SQL expression"/>
<formula>SQL expression</formula>
<many-to-one name="homeAddress" class="Address"
        insert="false" update="false">
    <column name="person_id" not-null="true" length="10"/>
    <formula>'MAILING'</formula>
</many-to-one>
<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
    <column name="first_string"/>
    <column name="second_string"/>
</property>
<property name="priority">
    <type name="com.mycompany.usertypes.DefaultValueIntegerType">
        <param name="default">0</param>
    </type>
</property>
<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
    <param name="default">0</param>
</typedef>
<property name="priority" type="default_zero"/>
<class name="Contract" table="Contracts"
        entity-name="CurrentContract">
    ...
    <set name="history" inverse="true"
            order-by="effectiveEndDate desc">
        <key column="currentContractId"/>
        <one-to-many entity-name="HistoricalContract"/>
    </set>
</class>

<class name="Contract" table="ContractHistory"
        entity-name="HistoricalContract">
    ...
    <many-to-one name="currentContract"
            column="currentContractId"
            entity-name="CurrentContract"/>
</class>

注意

This feature is not supported in Annotations

@Entity @Table(name="`Line Item`")
class LineItem {
   @id @Column(name="`Item Id`") Integer id;
   @Column(name="`Item #`") int itemNumber
}

<class name="LineItem" table="`Line Item`">
    <id name="id" column="`Item Id`"/><generator class="assigned"/></id>
    <property name="itemNumber" column="`Item #`"/>
    ...
</class>
@Entity

class CreditCard {
   @Column(name="credit_card_num")
   @ColumnTransformer(
      read="decrypt(credit_card_num)", 
      write="encrypt(?)")
   public String getCreditCardNumber() { return creditCardNumber; }
   public void setCreditCardNumber(String number) { this.creditCardNumber = number; }
   private String creditCardNumber;
}
<property name="creditCardNumber">
        <column 
          name="credit_card_num"
          read="decrypt(credit_card_num)"
          write="encrypt(?)"/>
</property>

注意

You can use the plural form @ColumnTransformers if more than one columns need to define either of these rules.

@Entity

class User {
   @Type(type="com.acme.type.CreditCardType")
   @Columns( {
      @Column(name="credit_card_num"),
      @Column(name="exp_date") } )
   @ColumnTransformer(
      forColumn="credit_card_num", 
      read="decrypt(credit_card_num)", 
      write="encrypt(?)")
   public CreditCard getCreditCard() { return creditCard; }
   public void setCreditCard(CreditCard card) { this.creditCard = card; }
   private CreditCard creditCard;
}
  • 属性由一个或多个属性组成,它作为自动模式生成的一部分导出。

  • 属性是可读写的,非只读的。

<hibernate-mapping>
    ...
    <database-object>
        <create>CREATE TRIGGER my_trigger ...</create>
        <drop>DROP TRIGGER my_trigger</drop>
    </database-object>
</hibernate-mapping>
<hibernate-mapping>
    ...
    <database-object>
        <definition class="MyTriggerDefinition"/>
    </database-object>
</hibernate-mapping>
<hibernate-mapping>
    ...
    <database-object>
        <definition class="MyTriggerDefinition"/>
        <dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>
        <dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>
    </database-object>
</hibernate-mapping>

注意

This feature is not supported in Annotations