- 声明实体Bean
- @Entity
- public class Flight implements Serializable {
- Long id;
- @Id
- public Long getId() { return id; }
- public void setId(Long id) { this.id = id; }
- }
- @Entity 注解将一个类声明为实体 Bean, @Id 注解声明了该实体Bean的标识属性。
- Hibernate 可以对类的属性或者方法进行注解。属性对应field类别,方法的 getXxx()对应property类别。
- 定义表
- 通过 @Table 为实体Bean指定对应数据库表,目录和schema的名字。
- @Entity
- @Table(name="tbl_sky")
- public class Sky implements Serializable {
- ...
- @Table 注解包含一个schema和一个catelog 属性,使用@UniqueConstraints 可以定义表的唯一约束。
- @Table(name="tbl_sky",
- uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})}
- )
- 上述代码在 "month" 和 "day" 两个 field 上加上 unique constrainst.
- @Version 注解用于支持乐观锁版本控制。
- @Entity
- public class Flight implements Serializable {
- ...
- @Version
- @Column(name="OPTLOCK")
- public Integer getVersion() { ... }
- }
- version属性映射到 "OPTLOCK" 列,entity manager 使用这个字段来检测冲突。 一般可以用 数字 或者 timestamp 类型来支持 version.
- 实体Bean中所有非static 非 transient 属性都可以被持久化,除非用@Transient注解。
- 默认情况下,所有属性都用 @Basic 注解。
- 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
- 上述代码中 counter, lengthInMeter 属性将忽略不被持久化,而 firstname, name, length 被定义为可持久化和可获取的。
- @TemporalType.(DATE,TIME,TIMESTAMP) 分别Map java.sql.(Date, Time, Timestamp).
- @Lob 注解属性将被持久化为 Blog 或 Clob 类型。具体的java.sql.Clob, Character[], char[] 和 java.lang.String 将被持久化为 Clob 类型. java.sql.Blob, Byte[], byte[] 和 serializable type 将被持久化为 Blob 类型。
- @Lob
- public String getFullText() {
- return fullText; // clob type
- }
- @Lob
- public byte[] getFullCode() {
- return fullCode; // blog type
- }
- @Column 注解将属性映射到列。
- @Entity
- public class Flight implements Serializable {
- ...
- @Column(updatable = false, name = "flight_name", nullable = false, length=50)
- public String getName() { ... }
- 定义 name 属性映射到 flight_name column, not null, can't update, length equal 50
- @Column(
- name="columnName"; (1) 列名
- boolean unique() default false; (2) 是否在该列上设置唯一约束
- boolean nullable() default true; (3) 列可空?
- boolean insertable() default true; (4) 该列是否作为生成 insert语句的一个列
- boolean updatable() default true; (5) 该列是否作为生成 update语句的一个列
- String columnDefinition() default ""; (6) 默认值
- String table() default ""; (7) 定义对应的表(deault 是主表)
- int length() default 255; (8) 列长度
- int precision() default 0; // decimal precision (9) decimal精度
- int scale() default 0; // decimal scale (10) decimal长度
- 嵌入式对象(又称组件)也就是别的对象定义的属性
- 组件类必须在类一级定义 @Embeddable 注解。在特定的实体关联属性上使用 @Embeddable 和 @AttributeOverride 注解可以覆盖该属性对应的嵌入式对象的列映射。
- @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; }
- ...
- }
- Person 类定义了 Address 和 Country 对象,具体两个类实现见上。
- 无注解属性默认值:
- • 属性为简单类型,则映射为 @Basic
- • 属性对应的类型定义了 @Embeddable 注解,则映射为 @Embedded
- • 属性对应的类型实现了Serializable,则属性被映射为@Basic并在一个列中保存该对象的serialized版本。
- • 属性的类型为 java.sql.Clob or java.sql.Blob, 则映射到 @Lob 对应的类型。
- 映射主键属性
- @Id 注解可将实体Bean中某个属性定义为主键,使用@GenerateValue注解可以定义该标识符的生成策略。
- • AUTO - 可以是 identity column, sequence 或者 table 类型,取决于不同底层的数据库
- • TABLE - 使用table保存id值
- • IDENTITY - identity column
- • SEQUENCE - seque
- nce
- @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
- public Integer getId() { ... }
- @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
- public Long getId() { ... }
- AUTO 生成器,适用与可移值的应用,多个@Id可以共享同一个 identifier生成器,只要把generator属性设成相同的值就可以。通过@SequenceGenerator 和 @TableGenerator 可以配置不同的 identifier 生成器。
- <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
- )
- The next example shows the definition of a sequence generator in a class scope:
- @Entity
- @javax.persistence.SequenceGenerator(
- name="SEQ_STORE",
- sequenceName="my_sequence"
- )
- public class Store implements Serializable {
- private Long id;
- @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
- public Long getId() { return id; }
- }
- Store类使用名为my_sequence的sequence,并且SEQ_STORE生成器对于其他类是不可见的。
- 通过下面语法,你可以定义组合键。
- • 将组件类注解为 @Embeddable, 并将组件的属性注解为 @Id
- • 将组件的属性注解为 @EmbeddedId
- • 将类注解为 @IdClass,并将该实体中所有主键的属性都注解为 @Id
- @Entity
- @IdClass(FootballerPk.class)
- public class Footballer {
- //part of the id key
- @Id public String getFirstname() {
- return firstname;
- }
- public void setFirstname(String firstname) {
- this.firstname = firstname;
- }
- //part of the id key
- @Id public String getLastname() {
- return lastname;
- }
- public void setLastname(String lastname) {
- this.lastname = lastname;
- }
- public String getClub() {
- return club;
- }
- public void setClub(String club) {
- this.club = club;
- }
- //appropriate equals() and hashCode() implementation
- }
- @Embeddable
- public class FootballerPk implements Serializable {
- //same name and type as in Footballer
- public String getFirstname() {
- return firstname;
- }
- public void setFirstname(String firstname) {
- this.firstname = firstname;
- }
- //same name and type as in Footballer
- public String getLastname() {
- return lastname;
- }
- public void setLastname(String lastname) {
- this.lastname = lastname;
- }
- //appropriate equals() and hashCode() implementation
- }
- @Entity
- @AssociationOverride( name="id.channel", joinColumns = @JoinColumn(name="chan_id") )
- public class TvMagazin {
- @EmbeddedId public TvMagazinPk id;
- @Temporal(TemporalType.TIME) Date time;
- }
- @Embeddable
- public class TvMagazinPk implements Serializable {
- @ManyToOne
- public Channel channel;
- public String name;
- @ManyToOne
- public Presenter presenter;
- }
- 映射继承关系
- EJB支持3种类型的继承。
- • Table per Class Strategy: the <union-class> element in Hibernate 每个类一张表
- • Single Table per Class Hierarchy Strategy: the <subclass> element in Hibernate 每个类层次结构一张表
- • Joined Subclass Strategy: the <joined-subclass> element in Hibernate 连接的子类策略
- @Inheritance 注解来定义所选的之类策略。
- 每个类一张表
- @Entity
- @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
- public class Flight implements Serializable {
- 有缺点,如多态查询或关联。Hibernate 使用 SQL Union 查询来实现这种策略。 这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个表间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。
- 每个类层次结构一张表
- @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)来区分。
- Plane 是父类。@DiscriminatorColumn 注解定义了辨别符列。对于继承层次结构中的每个类, @DiscriminatorValue 注解指定了用来辨别该类的值。 辨别符列名字默认为 DTYPE,其默认值为实体名。其类型为DiscriminatorType.STRING。
- 连接的子类
- @Entity
- @Inheritance(strategy=InheritanceType.JOINED)
- public class Boat implements Serializable { ... }
- @Entity
- public class Ferry extends Boat { ... }
- @Entity
- @PrimaryKeyJoinColumn(name="BOAT_ID")
- public class AmericaCupClass extends Boat { ... }
- 以上所有实体使用 JOINED 策略 Ferry和Boat class使用同名的主键关联(eg: Boat.id = Ferry.id), AmericaCupClass 和 Boat 关联的条件为 Boat.id = AmericaCupClass.BOAT_ID.
- 从父类继承的属性
- @MappedSuperclass
- public class BaseEntity {
- @Basic
- @Temporal(TemporalType.TIMESTAMP)
- public Date getLastUpdate() { ... }
- public String getLastUpdater() { ... }
- ...
- }
- @Entity class Order extends BaseEntity {
- @Id public Integer getId() { ... }
- ...
- }
- 继承父类的一些属性,但不用父类作为映射实体,这时候需要 @MappedSuperclass 注解。 上述实体映射到数据库中的时候对应 Order 实体Bean, 其具有 id, lastUpdate, lastUpdater 三个属性。如果没有@MappedSuperclass 注解,则父类中属性忽略,这是 Order 实体 Bean 只有 id 一个属性。
- 映射实体Bean的关联关系
- 一对一
- 使用 @OneToOne 注解可以建立实体Bean之间的一对一关系。一对一关系有3种情况。
- • 关联的实体都共享同样的主键。
- @Entity
- public class Body {
- @Id
- public Long getId() { return id; }
- @OneToOne(cascade = CascadeType.ALL)
- @PrimaryKeyJoinColumn
- public Heart getHeart() {
- return heart;
- }
- ...
- }
- @Entity
- public class Heart {
- @Id
- public Long getId() { ...}
- }
- 通过@PrimaryKeyJoinColumn 注解定义了一对一的关联关系。
- 多对一
- 使用 @ManyToOne 注解定义多对一关系。
- @Entity()
- public class Flight implements Serializable {
- @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
- @JoinColumn(name="COMP_ID")
- public Company getCompany() {
- return company;
- }
- ...
- }
- 其中@JoinColumn 注解是可选的,关键字段默认值和一对一关联的情况相似。列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。本例中为company_id,因为关联的属性是company, Company的主键为 id.
- @ManyToOne 注解有个targetEntity属性,该参数定义了目标实体名。通常不需要定义,大部分情况为默认值。但下面这种情况则需要 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;
- }
- ...
- }
- 集合类型
- 一对多
- @OneToMany 注解可定义一对多关联。一对多关联可以是双向的。
- 双向
- 规范中多对一端几乎总是双向关联中的主体(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 端不必也不能定义任何物理映射。
- 单向
- @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
- }
- 一般通过连接表来实现这种关联,可以通过@JoinColumn注解来描述这种单向关联关系。上例 Customer 通过 CUST_ID 列和 Ticket 建立了单向关联关系。
- 通过关联表来处理单向关联
- @E
hibernate注解使用
最新推荐文章于 2024-09-11 22:50:11 发布