Hibernate Annotation
继承策略:Singletableperclasshierarchystrategy
@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 { ... }
table-per-subclass:
@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; } }
Tableperclassstrategy:
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Flight implements Serializable { ... }
Inheritpropertiesfromsuperclasses:
//某些表有共同属性但不必把超类持久化 @MappedSuperclass public class BaseEntity { @Basic @Temporal(TemporalType.TIMESTAMP) public Date getLastUpdate() { ... } public String getLastUpdater() { ... } ... } @Entity class Order extends BaseEntity { @Id public Integer getId() { ... } ... }
覆盖超类的字段:
@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 { ... }
Mappingonetooneandonetomanyassociations:
cascade属性:级联操作
Bydefault,singlepointassociationsareeagerlyfetchedinJPA2.Youcanmarkitaslazilyfetchedbyusing@ManyToOne(fetch=FetchType.LAZY)inwhichcaseHibernatewillproxytheassociationandloaditwhenthestateoftheassociatedentityisreached.:单端关联使用Annotationlazy默认为false
Usingaforeignkeyoranassociationtable:
@Entity public class Flight implements Serializable { @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinColumn(name="COMP_ID") public Company getCompany() { return company; } ... }
The@JoinColumnattributeisoptional:上例默认为company_id
Youcanalsomapatooneassociationthroughanassociationtable:关联表关联
@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; } ... }
关联对象找不到时的处理:
@Entity public class Child { ... @ManyToOne @NotFound(action=NotFoundAction.IGNORE) public Parent getParent() { ... } ... }
改变外键名称:
@Entity
public class Child { ... @ManyToOne @ForeignKey(name="FK_PARENT") public Parent getParent() { ... } ... }
关联非主键以外的属性:
@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 }
拥有相同主键:
@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() { ...} }
Howtomapcollections:
@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 { ... }
Collectionmappingusing@OneToManyand@JoinTable:关联表方式
@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 { ... }
对于单向一对多关联:外键默认为空,可能需要设置@JoinColumn(nullable=false)
排序的List
@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; }
--Tableschema
|-------------||----------|
|Order||Customer|
|-------------||----------|
|id||id|
|number||----------|
|customer_id|
|-------------|
存储集合的Key:
@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; }
此处的mappedBy相当于inverse,只出现在双向关联中,mappedBy的另一方为外键的持有方,只要另一方维护了关联,就不需要双方的维护了了
Maps:
@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; }
--Tableschema
|-------------||----------|
|Order||Customer|
|-------------||----------|
|id||id|
|number||----------|
|customer_id|
|-------------|
双向关联
@Entity public class Troop { @OneToMany(mappedBy="troop") public Set<Soldier> getSoldiers() { ... } @Entity public class Soldier { @ManyToOne @JoinColumn(name="troop_fk") public Troop getTroop() { ... }
Manytomanyassociationvia@ManyToMany
@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; } }
<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>
上面的map-key有对应的列
<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>
没有对应列的时候,不能使用inverse=true,参上面代码
public class Parent { @Id @GeneratedValue private long id; @OneToMany([color=red]optional=false[/color]) private Set<Child> children; // getter/setter ... } public class Child { @Id @GeneratedValue private long id; private String name; // getter/setter ... }
optional=false相当于外键不能为空
persist()使一个临时实例持久化。然而,它不保证立即把标识符值分配给持久性实例,这会发生在冲刷(flush)的时候。persist()也保证它在事务边界外调用时不会执行INSERT语句。这对于长期运行的带有扩展会话/持久化上下文的会话是很有用的。
save()保证返回一个标识符。如果需要运行INSERT来获取标识符(如"identity"而非"sequence"生成器),这个INSERT将立即执行,不管你是否在事务内部还是外部。这对于长期运行的带有扩展会话/持久化上下文的会话来说会出现问题。