diff --git a/annotations/src/main/docbook/en/modules/entity.xml b/annotations/src/main/docbook/en/modules/entity.xml
index bc000f40ab..24db0a730c 100644
--- a/annotations/src/main/docbook/en/modules/entity.xml
+++ b/annotations/src/main/docbook/en/modules/entity.xml
@@ -60,9 +60,8 @@
Marking a POJO as persistent entity
- Every persistent POJO class is an entity bean and is declared
- using the @Entity annotation (at the class
- level):
+ Every persistent POJO class is an entity and is declared using the
+ @Entity annotation (at the class level):
@Entity
public class Flight implements Serializable {
@@ -74,11 +73,11 @@ public class Flight implements Serializable {
public void setId(Long id) { this.id = id; }
}
- @Entity declares the class as an entity bean
- (i.e. a persistent POJO class), @Id declares the
- identifier property of this entity bean. The other mapping declarations
- are implicit. The class Flight is mapped to the Flight table, using the
- column id as its primary key column.
+ @Entity declares the class as an entity (i.e. a
+ persistent POJO class), @Id declares the identifier
+ property of this entity. The other mapping declarations are implicit.
+ The class Flight is mapped to the Flight table, using the column id as
+ its primary key column.
The concept of configuration by exception is central to the JPA
@@ -100,8 +99,8 @@ public class Flight implements Serializable {
@Table is set at the class level; it allows
you to define the table, catalog, and schema names for your entity
- bean mapping. If no @Table is defined the default
- values are used: the unqualified class name of the entity.
+ mapping. If no @Table is defined the default values
+ are used: the unqualified class name of the entity.
@Entity
@Table(name="tbl_sky")
@@ -140,8 +139,8 @@ public class Sky implements Serializable {
Versioning for optimistic locking
- You can add optimistic locking capability to an entity bean
- using the @Version annotation:
+ You can add optimistic locking capability to an entity using the
+ @Version annotation:
@Entity
public class Flight implements Serializable {
@@ -176,12 +175,12 @@ public class Flight implements Serializable {
Declaring basic property mappings
Every non static non transient property (field or method
- depending on the access type) of an entity bean is considered
- persistent, unless you annotate it as @Transient.
- Not having an annotation for your property is equivalent to the
- appropriate @Basic annotation. The
- @Basic annotation allows you to declare the
- fetching strategy for a property:
+ depending on the access type) of an entity is considered persistent,
+ unless you annotate it as @Transient. Not having an
+ annotation for your property is equivalent to the appropriate
+ @Basic annotation. The @Basic
+ annotation allows you to declare the fetching strategy for a
+ property:
public transient int counter; //transient property
@@ -568,7 +567,7 @@ public class Country implements Serializable {
entity (note that you can override that using the
@Access annotation).
- The Person entity bean has two component
+ The Person entity has two component
properties, homeAddress and
bornIn. homeAddress property has
not been annotated, but Hibernate will guess that it is a persistent
@@ -654,9 +653,9 @@ public class Country implements Serializable {
Mapping identifier properties
The @Id annotation lets you define which
- property is the identifier of your entity bean. This property can be set
- by the application itself or be generated by Hibernate (preferred). You
- can define the identifier generation strategy thanks to the
+ property is the identifier of your entity. This property can be set by
+ the application itself or be generated by Hibernate (preferred). You can
+ define the identifier generation strategy thanks to the
@GeneratedValue annotation.
@@ -1404,7 +1403,7 @@ public class Plane extends FlyingObject {
One-to-one
- You can associate entity beans through a one-to-one relationship
+ You can associate entities through a one-to-one relationship
using @OneToOne. There are three cases for
one-to-one associations: either the associated entities share the same
primary keys values, a foreign key is held by one of the entities
@@ -1496,8 +1495,7 @@ public class Passport implements Serializable {
The third possibility (using an association table) is quite
exotic.
-
-@Entity
+ @Entity
public class Customer implements Serializable {
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(name = "CustomerPassports",
@@ -1513,8 +1511,7 @@ public class Passport implements Serializable {
@OneToOne(mappedBy = "passport")
public Customer getOwner() {
...
-}
-
+}
A Customer is linked to a
Passport through a association table named
@@ -1601,20 +1598,392 @@ public class Flight implements Serializable {
Collections
+ You can map Collection,
+ List, Map and
+ Set pointing to associated entities as
+ one-to-many or many-to-many associations using the
+ @OneToMany or
+ @ManyToMany annotation respectively. If the
+ collection is of a basic type or of an embeddable type, use
+ @ElementCollection. We will describe that in
+ more detail in the following subsections.
+
+
+ One-to-many
+
+ One-to-many associations are declared at the property level
+ with the annotation @OneToMany. One to many
+ associations may be bidirectional.
+
+
+ Bidirectional
+
+ Since many to one are (almost) always the owner side of a
+ bidirectional relationship in the JPA spec, the one to many
+ association is annotated by
+ @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 has a bidirectional one to many
+ relationship with Soldier through the
+ troop property. You don't have to (must not)
+ define any physical mapping in the mappedBy
+ side.
+
+ To map a bidirectional one to many, with the one-to-many
+ side as the owning side, you have to remove the
+ mappedBy element and set the many to one
+ @JoinColumn as insertable and updatable to
+ false. This solution is not optimized and will produce some
+ additional UPDATE statements.
+
+ @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() {
+ ...
+}
+
+
+
+ Unidirectional
+
+ A unidirectional one to many using a foreign key column in
+ the owned entity is not that common and not really recommended. We
+ strongly advise you to use a join table for this kind of
+ association (as explained in the next section). This kind of
+ association is described through a
+ @JoinColumn
+
+ @Entity
+public class Customer implements Serializable {
+ @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+ @JoinColumn(name="CUST_ID")
+ public Set<Ticket> getTickets() {
+ ...
+}
+
+@Entity
+public class Ticket implements Serializable {
+ ... //no bidir
+}
+
+ Customer describes a unidirectional
+ relationship with Ticket using the join column
+ CUST_ID.
+
+
+
+ Unidirectional with join table
+
+ A unidirectional one to many with join table is much
+ preferred. This association is described through an
+ @JoinTable.
+
+ @Entity
+public class Trainer {
+ @OneToMany
+ @JoinTable(
+ name="TrainedMonkeys",
+ joinColumns = @JoinColumn( name="trainer_id"),
+ inverseJoinColumns = @JoinColumn( name="monkey_id")
+ )
+ public Set<Monkey> getTrainedMonkeys() {
+ ...
+}
+
+@Entity
+public class Monkey {
+ ... //no bidir
+}
+
+ Trainer describes a unidirectional
+ relationship with Monkey using the join
+ table TrainedMonkeys, with a foreign key
+ trainer_id to Trainer
+ (joinColumns) and a foreign key
+ monkey_id to Monkey
+ (inversejoinColumns).
+
+
+
+ Defaults
+
+ Without describing any physical mapping, a unidirectional
+ one to many with join table is used. The table name is the
+ concatenation of the owner table name, _, and the
+ other side table name. The foreign key name(s) referencing the
+ owner table is the concatenation of the owner table,
+ _, and the owner primary key column(s) name. The
+ foreign key name(s) referencing the other side is the
+ concatenation of the owner property name, _, and
+ the other side primary key column(s) name. A unique constraint is
+ added to the foreign key referencing the other side table to
+ reflect the one to many.
+
+ @Entity
+public class Trainer {
+ @OneToMany
+ public Set<Tiger> getTrainedTigers() {
+ ...
+}
+
+@Entity
+public class Tiger {
+ ... //no bidir
+}
+
+ Trainer describes a unidirectional
+ relationship with Tiger using the join
+ table Trainer_Tiger, with a foreign key
+ trainer_id to Trainer (table
+ name, _, trainer id) and a foreign key
+ trainedTigers_id to Monkey
+ (property name, _, Tiger primary column).
+
+
+
+
+ Many-to-many
+
+
+ Definition
+
+ A many-to-many association is defined logically using the
+ @ManyToMany annotation. You also have to
+ describe the association table and the join conditions using the
+ @JoinTable annotation. If the association is
+ bidirectional, one side has to be the owner and one side has to be
+ the inverse end (ie. it will be ignored when updating the
+ relationship values in the association table):
+
+ @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;
+ }
+}
+
+ We've already shown the many declarations and the detailed
+ attributes for associations. We'll go deeper in the
+ @JoinTable description, it defines a
+ name, an array of join columns (an array in
+ annotation is defined using { A, B, C }), and an array of inverse
+ join columns. The latter ones are the columns of the association
+ table which refer to the Employee primary
+ key (the "other side").
+
+ As seen previously, the other side don't have to (must not)
+ describe the physical mapping: a simple
+ mappedBy argument containing the owner side
+ property name bind the two.
+
+
+
+ Default values
+
+ As any other annotations, most values are guessed in a many
+ to many relationship. Without describing any physical mapping in a
+ unidirectional many to many the following rules applied. The table
+ name is the concatenation of the owner table name,
+ _ and the other side table name. The foreign key
+ name(s) referencing the owner table is the concatenation of the
+ owner table name, _ and the owner primary key
+ column(s). The foreign key name(s) referencing the other side is
+ the concatenation of the owner property name, _,
+ and the other side primary key column(s). These are the same rules
+ used for a unidirectional one to many relationship.
+
+
+@Entity
+public class Store {
+ @ManyToMany(cascade = CascadeType.PERSIST)
+ public Set<City> getImplantedIn() {
+ ...
+ }
+}
+
+@Entity
+public class City {
+ ... //no bidirectional relationship
+}
+
+
+ A Store_City is used as the join table.
+ The Store_id column is a foreign key to the
+ Store table. The
+ implantedIn_id column is a foreign key to the
+ City table.
+
+ Without describing any physical mapping in a bidirectional
+ many to many the following rules applied. The table name is the
+ concatenation of the owner table name, _ and the
+ other side table name. The foreign key name(s) referencing the
+ owner table is the concatenation of the other side property name,
+ _, and the owner primary key column(s). The
+ foreign key name(s) referencing the other side is the
+ concatenation of the owner property name, _, and
+ the other side primary key column(s). These are the same rules
+ used for a unidirectional one to many 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() {
+ ...
+ }
+}
+
+ A Store_Customer is used as the join
+ table. The stores_id column is a foreign key to
+ the Store table. The
+ customers_id column is a foreign key to the
+ Customer table.
+
+
+
+
+ Collection of basic types or embeddable objects
+
+ In some simple situation, do don't need to associate two
+ entities but simply create a collection of basic types or embeddable
+ objects. Use the @ElementCollection in this
+ case.
+
+ @Entity
+public class User {
+ [...]
+ public String getLastname() { ...}
+
+ @ElementCollection
+ @CollectionTable(name="Nicknames", joinColumns=@JoinColumn(name="user_id"))
+ @Column(name="nickname")
+ public Set<String> getNicknames() { ... }
+}
+
+ The collection table holding the collection data is set using
+ the @CollectionTable annotation. If omitted
+ the collection table name default to the concatenation of the name
+ of the containing entity and the name of the collection attribute,
+ separated by an underscore: in our example, it would be
+ User_nicknames.
+
+ The column holding the basic type is set using the
+ @Column annotation. If omitted, the column
+ name defaults to the property name: in our example, it would be
+ nicknames.
+
+ But you are not limited to basic types, the collection type
+ can be any embeddable object. To override the columns of the
+ embeddable object in the collection table, use the
+ @AttributeOverride annotation.
+
+ @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() {...}
+ [...]
+}
+
+ Such an embeddable object cannot contains a collection
+ itself.
+
+
+ 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.
+
+
+
- Overview
-
- You can map Collection,
- List, Map and
- Set pointing to associated entities as
- one-to-many or many-to-many associations using the
- @OneToMany or
- @ManyToMany annotation respectively. If the
- collection is of a basic type or of an embeddable type, use
- @ElementCollection. We will describe that in
- more detail in the following subsections but let's first focus on
- some semantic differences between the various collections.
+ Indexed collections (List, Map)
Lists can be mapped in two different ways:
@@ -1864,6 +2233,13 @@ public class Order {
| 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.
+
+
Let's now explore the various collection semantics based on
the mapping you are choosing.
@@ -1946,308 +2322,6 @@ public class Order {
More support for collections are available via Hibernate
specific extensions (see ).
-
-
- One-to-many
-
- One-to-many associations are declared at the property level
- with the annotation @OneToMany. One to many
- associations may be bidirectional.
-
-
- Bidirectional
-
- Since many to one are (almost) always the owner side of a
- bidirectional relationship in the EJB3 spec, the one to many
- association is annotated by @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 has a bidirectional one to many
- relationship with Soldier through the
- troop property. You don't have to (must not)
- define any physical mapping in the mappedBy
- side.
-
- To map a bidirectional one to many, with the one-to-many
- side as the owning side, you have to remove the
- mappedBy element and set the many to one
- @JoinColumn as insertable and updatable to
- false. This solution is obviously not optimized and will produce
- some additional UPDATE statements.
-
- @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() {
- ...
-}
-
-
-
- Unidirectional
-
- A unidirectional one to many using a foreign key column in
- the owned entity is not that common and not really recommended. We
- strongly advise you to use a join table for this kind of
- association (as explained in the next section). This kind of
- association is described through a
- @JoinColumn
-
-
-@Entity
-public class Customer implements Serializable {
- @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
- @JoinColumn(name="CUST_ID")
- public Set<Ticket> getTickets() {
- ...
-}
-
-@Entity
-public class Ticket implements Serializable {
- ... //no bidir
-}
-
-
- Customer describes a unidirectional
- relationship with Ticket using the join column
- CUST_ID.
-
-
-
- Unidirectional with join table
-
- A unidirectional one to many with join table is much
- preferred. This association is described through an
- @JoinTable.
-
-
-@Entity
-public class Trainer {
- @OneToMany
- @JoinTable(
- name="TrainedMonkeys",
- joinColumns = @JoinColumn( name="trainer_id"),
- inverseJoinColumns = @JoinColumn( name="monkey_id")
- )
- public Set<Monkey> getTrainedMonkeys() {
- ...
-}
-
-@Entity
-public class Monkey {
- ... //no bidir
-}
-
-
- Trainer describes a unidirectional
- relationship with Monkey using the join
- table TrainedMonkeys, with a foreign key
- trainer_id to Trainer
- (joinColumns) and a foreign key
- monkey_id to Monkey
- (inversejoinColumns).
-
-
-
- Defaults
-
- Without describing any physical mapping, a unidirectional
- one to many with join table is used. The table name is the
- concatenation of the owner table name, _, and the
- other side table name. The foreign key name(s) referencing the
- owner table is the concatenation of the owner table,
- _, and the owner primary key column(s) name. The
- foreign key name(s) referencing the other side is the
- concatenation of the owner property name, _, and
- the other side primary key column(s) name. A unique constraint is
- added to the foreign key referencing the other side table to
- reflect the one to many.
-
-
-@Entity
-public class Trainer {
- @OneToMany
- public Set<Tiger> getTrainedTigers() {
- ...
-}
-
-@Entity
-public class Tiger {
- ... //no bidir
-}
-
-
- Trainer describes a unidirectional
- relationship with Tiger using the join
- table Trainer_Tiger, with a foreign key
- trainer_id to Trainer (table
- name, _, trainer id) and a foreign key
- trainedTigers_id to Monkey
- (property name, _, Tiger primary column).
-
-
-
-
- Many-to-many
-
-
- Definition
-
- A many-to-many association is defined logically using the
- @ManyToMany annotation. You also have to
- describe the association table and the join conditions using the
- @JoinTable annotation. If the association is
- bidirectional, one side has to be the owner and one side has to be
- the inverse end (ie. it will be ignored when updating the
- relationship values in the association table):
-
-
-@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;
- }
-}
-
-
- We've already shown the many declarations and the detailed
- attributes for associations. We'll go deeper in the
- @JoinTable description, it defines a
- name, an array of join columns (an array in
- annotation is defined using { A, B, C }), and an array of inverse
- join columns. The latter ones are the columns of the association
- table which refer to the Employee primary
- key (the "other side").
-
- As seen previously, the other side don't have to (must not)
- describe the physical mapping: a simple
- mappedBy argument containing the owner side
- property name bind the two.
-
-
-
- Default values
-
- As any other annotations, most values are guessed in a many
- to many relationship. Without describing any physical mapping in a
- unidirectional many to many the following rules applied. The table
- name is the concatenation of the owner table name,
- _ and the other side table name. The foreign key
- name(s) referencing the owner table is the concatenation of the
- owner table name, _ and the owner primary key
- column(s). The foreign key name(s) referencing the other side is
- the concatenation of the owner property name, _,
- and the other side primary key column(s). These are the same rules
- used for a unidirectional one to many relationship.
-
-
-@Entity
-public class Store {
- @ManyToMany(cascade = CascadeType.PERSIST)
- public Set<City> getImplantedIn() {
- ...
- }
-}
-
-@Entity
-public class City {
- ... //no bidirectional relationship
-}
-
-
- A Store_City is used as the join table.
- The Store_id column is a foreign key to the
- Store table. The
- implantedIn_id column is a foreign key to the
- City table.
-
- Without describing any physical mapping in a bidirectional
- many to many the following rules applied. The table name is the
- concatenation of the owner table name, _ and the
- other side table name. The foreign key name(s) referencing the
- owner table is the concatenation of the other side property name,
- _, and the owner primary key column(s). The
- foreign key name(s) referencing the other side is the
- concatenation of the owner property name, _, and
- the other side primary key column(s). These are the same rules
- used for a unidirectional one to many 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() {
- ...
- }
-}
-
-
- A Store_Customer is used as the join
- table. The stores_id column is a foreign key to
- the Store table. The
- customers_id column is a foreign key to the
- Customer table.
-
-
@@ -2255,35 +2329,40 @@ public class Customer {
You probably have noticed the cascade
attribute taking an array of CascadeType as a
- value. The cascade concept in EJB3 is very is similar to the
- transitive persistence and cascading of operations in Hibernate, but
- with slightly different semantics and cascading types:
+ value. The cascade concept in JPA is very is similar to the transitive
+ persistence and cascading of operations in Hibernate, but with
+ slightly different semantics and cascading types:
- CascadeType.PERSIST: cascades the persist (create) operation
- to associated entities persist() is called or if the entity is
- managed
+ CascadeType.PERSIST: cascades the persist
+ (create) operation to associated entities persist() is called or
+ if the entity is managed
- CascadeType.MERGE: cascades the merge operation to
- associated entities if merge() is called or if the entity is
- managed
+ CascadeType.MERGE: cascades the merge
+ operation to associated entities if merge() is called or if the
+ entity is managed
- CascadeType.REMOVE: cascades the remove operation to
- associated entities if delete() is called
+ CascadeType.REMOVE: cascades the remove
+ operation to associated entities if delete() is called
- CascadeType.REFRESH: cascades the refresh operation to
- associated entities if refresh() is called
+ CascadeType.REFRESH: cascades the refresh
+ operation to associated entities if refresh() is called
- CascadeType.ALL: all of the above
+ CascadeType.DETACH: cascades the detach
+ operation to associated entities if detach() is called
+
+
+
+ CascadeType.ALL: all of the above
@@ -2293,8 +2372,30 @@ public class Customer {
linkend="entity-hibspec-cascade" /> for more information
- Please refer to the chapter 6.3 of the EJB3 specification for
+ Please refer to the chapter 6.3 of the JPA specification for
more information on cascading and create/merge semantics.
+
+ You can also enable the orphan removal semantic. If an entity is
+ removed from a @OneToMany collection or an
+ associated entity is dereferenced from a
+ @OneToOne association, this associated entity
+ can be marked for deletion if orphanRemoval is set
+ to true. In a way, it means that the associated entity's lifecycle is
+ bound to the owning entity just like an embeddable object is.
+
+ @Entity class Customer {
+ @OneToMany(orphanRemoval=true) public Set<Order> getOrders() { return orders; }
+ public void setOrders(Set<Order> orders) { this.orders = orders; }
+ private Set<Order> orders;
+
+ [...]
+}
+
+@Entity class Order { ... }
+
+Customer customer = em.get(Customer.class, 1l);
+Order order = em.get(Order.class, 1l);
+customer.getOrders().remove(order); //order will be deleted by cascade
@@ -2313,9 +2414,9 @@ public class Customer {
EAGER. For more information about static fetching,
check .
- The recommanded approach is to use LAZY onn
+ The recommanded approach is to use LAZY on
all static fetching definitions and override this choice dynamically
- through JPA-QL. JPA-QL has a fetch keyword that
+ through JP-QL. JP-QL has a fetch keyword that
allows you to override laziness when doing a particular query. This is
very useful to improve performance and is decided on a use case to use
case basis.
@@ -2323,7 +2424,8 @@ public class Customer {
- Mapping composite primary and foreign keys
+ Mapping composite primary keys and foreign keys to composite
+ primary keys
Composite primary keys use a embedded class as the primary key
representation, so you'd use the @Id and
@@ -2331,11 +2433,10 @@ public class Customer {
the @EmbeddedId annotation. Note that the dependent
class has to be serializable and implements
equals()/hashCode().
- You can also use @IdClass as described in .
+ You can also use @IdClass. These are more detailed in
+ .
-
-@Entity
+ @Entity
public class RegionalArticle implements Serializable {
@Id
@@ -2343,21 +2444,18 @@ public class RegionalArticle implements Serializable {
}
@Embeddable
-public class RegionalArticlePk implements Serializable { ... }
-
+public class RegionalArticlePk implements Serializable { ... }
or alternatively
-
-@Entity
+ @Entity
public class RegionalArticle implements Serializable {
@EmbeddedId
public RegionalArticlePk getPk() { ... }
}
-public class RegionalArticlePk implements Serializable { ... }
-
+public class RegionalArticlePk implements Serializable { ... }
@Embeddable inherit the access type of its
owning entity unless @Access is used. Composite
@@ -2368,8 +2466,7 @@ public class RegionalArticlePk implements Serializable { ... }
explicitly. Otherwise, Hibernate will suppose that you use the same
order of columns as in the primary key declaration.
-
-@Entity
+ @Entity
public class Parent implements Serializable {
@Id
public ParentPk id;
@@ -2383,11 +2480,9 @@ public class Parent implements Serializable {
})
public Set<Child> children; //unidirectional
...
-}
-
+}
-
-@Entity
+ @Entity
public class Child implements Serializable {
@Id @GeneratedValue
public Integer id;
@@ -2399,17 +2494,14 @@ public class Child implements Serializable {
@JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
})
public Parent parent; //unidirectional
-}
-
+}
-
-@Embeddable
+ @Embeddable
public class ParentPk implements Serializable {
String firstName;
String lastName;
...
-}
-
+}
Note the explicit usage of the
referencedColumnName.
@@ -2418,15 +2510,14 @@ public class ParentPk implements Serializable {
Mapping secondary tables
- You can map a single entity bean to several tables using the
+ You can map a single entity to several tables using the
@SecondaryTable or
@SecondaryTables class level annotations. To express
that a column is in a particular table, use the table
parameter of @Column or
@JoinColumn.
-
-@Entity
+ @Entity
@Table(name="MainCat")
@SecondaryTables({
@SecondaryTable(name="Cat1", pkJoinColumns={
@@ -2459,7 +2550,7 @@ public class Cat implements Serializable {
public String getStoryPart2() {
return storyPart2;
}
-
+}
In this example, name will be in
MainCat. storyPart1 will be in
@@ -2479,16 +2570,33 @@ public class Cat implements Serializable {
Mapping Queries
+ While you can write queries in your code, it is considered a good
+ practice to externalize them:
+
+
+
+ it make developer/DBA communications easier
+
+
+
+ named queries are pre-compiled by Hibernate at startup
+ time
+
+
+
+ Unfortunately, you lose the type-safety of queries written using the
+ Criteria API.
+
- Mapping JPAQL/HQL queries
+ Mapping JP-QL/HQL queries
- You can map EJBQL/HQL queries using annotations.
+ You can map JP-QL/HQL queries using annotations.
@NamedQuery and @NamedQueries can
- be defined at the class level or in a JPA XML file. However their
- definitions are global to the session factory/entity manager factory
- scope. A named query is defined by its name and the actual query
- string.
+ be defined at the class level or in a JPA XML deployment descriptor.
+ However their definitions are global to the session factory/entity
+ manager factory scope. A named query is defined by its name and the
+ actual query string.
<entity-mappings>
<named-query name="plane.getAll">
@@ -2512,14 +2620,13 @@ public class MyDao {
...
}
...
-}
-
+}
You can also provide some hints to a query through an array of
QueryHint through a hints
attribute.
- The availabe Hibernate hints are
+ The available Hibernate hints are
@@ -2592,6 +2699,11 @@ public class MyDao {
+
+ You can also define the lock mode by which the returned entities
+ should be locked using the lockMode property. This is
+ equivalent to the optional lock mode of the entitymanager lookup
+ operations.
@@ -2618,10 +2730,10 @@ public class MyDao {
@NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "
+ " night.night_date, area.id aid, night.area_id, area.name "
- + "from Night night, Area area where night.area_id = area.id", resultSetMapping="joinMapping")
+ + "from Night night, Area area where night.area_id = area.id",
+ resultSetMapping="joinMapping")
@SqlResultSetMapping(name="joinMapping", entities={
- @EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = {
+ @EntityResult(entityClass=Night.class, fields = {
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@FieldResult(name="date", column="night_date"),
@@ -2643,8 +2755,11 @@ public class MyDao {
see an implicit declaration of the property / column.
@Entity
-@SqlResultSetMapping(name="implicit", entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class))
-@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultSetMapping="implicit")
+@SqlResultSetMapping(name="implicit",
+ entities=@EntityResult(entityClass=SpaceShip.class))
+@NamedNativeQuery(name="implicitSample",
+ query="select * from SpaceShip",
+ resultSetMapping="implicit")
public class SpaceShip {
private String name;
private String model;
@@ -2689,7 +2804,7 @@ public class SpaceShip {
@Entity
@SqlResultSetMapping(name="compositekey",
- entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class,
+ entities=@EntityResult(entityClass=SpaceShip.class,
fields = {
@FieldResult(name="name", column = "name"),
@FieldResult(name="model", column = "model"),
@@ -2786,13 +2901,6 @@ public class Captain implements Serializable {
}
-
- If you look at the dimension property, you'll see that Hibernate
- supports the dotted notation for embedded objects (you can even have
- nested embedded objects). EJB3 implementations do not have to support
- this feature, we do :-)
-
-
If you retrieve a single entity and if you use the default
mapping, you can use the resultClass attribute
instead of resultSetMapping:
@@ -3136,24 +3244,20 @@ public long getObjectVolume()
Place your annotations before the package declaration.
-
-@TypeDef(
- name = "phoneNumber",
- defaultForType = PhoneNumber.class,
- typeClass = PhoneNumberType.class
+ @TypeDef(
+ name = "phoneNumber",
+ defaultForType = PhoneNumber.class,
+ typeClass = PhoneNumberType.class
)
@Entity
public class ContactDetails {
- ...
- private PhoneNumber localPhoneNumber;
- @Type(type="phoneNumber")
- private OverseasPhoneNumber overseasPhoneNumber;
- ...
-}
-
-
-
+ [...]
+ private PhoneNumber localPhoneNumber;
+ @Type(type="phoneNumber")
+ private OverseasPhoneNumber overseasPhoneNumber;
+ [...]
+}
The following example shows the usage of the
parameters attribute to customize the
@@ -3178,8 +3282,7 @@ public class Forest {
@Type(type="caster")
public String getSmallText() {
...
-}
-
+}
When using composite user type, you will have to express column
definitions. The @Columns has been introduced for
@@ -3248,7 +3351,8 @@ person == person.address.owner
@Entity
public class Antenna {
@Id public Integer id;
- @Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false)
+ @Generated(GenerationTime.ALWAYS)
+ @Column(insertable = false, updatable = false)
public String longitude;
@Generated(GenerationTime.INSERT) @Column(insertable = false)
@@ -3257,10 +3361,11 @@ public class Antenna {
Annotate your property as @Generated You have
to make sure your insertability or updatability does not conflict with
- the generation strategy you have chosen. When GenerationTime.INSERT is
- chosen, the property must not contains insertable columns, when
- GenerationTime.ALWAYS is chosen, the property must not contains
- insertable nor updatable columns.
+ the generation strategy you have chosen. When
+ GenerationTime.INSERT is chosen, the property must
+ not contains insertable columns, when
+ GenerationTime.ALWAYS is chosen, the property must
+ not contains insertable nor updatable columns.
@Version properties cannot be
@Generated(INSERT) by design, it has to be either
@@ -3282,8 +3387,6 @@ public class Antenna {
public Owner getOwner() {
return owner;
}
-
-
@@ -3394,7 +3497,7 @@ alter table Child add constraint FK_PARENT foreign key (parent_id) references Pa
Lazy options and fetching modes
- EJB3 comes with the fetch option to define
+ JPA comes with the fetch option to define
lazy loading and fetching modes, however Hibernate has a much more
option set in this area. To fine tune the lazy loading and fetching
strategies, some additional annotations have been introduced:
@@ -3503,10 +3606,11 @@ alter table Child add constraint FK_PARENT foreign key (parent_id) references Pa
mapping (polymorphic) associations. You should use this only in very
special cases (eg. audit logs, user session data, etc).
- The @Any annotation describes the column holding the metadata
- information. To link the value of the metadata information and an
- actual entity type, The @AnyDef and
- @AnyDefs annotations are used.
+ The @Any annotation describes the column
+ holding the metadata information. To link the value of the metadata
+ information and an actual entity type, The
+ @AnyDef and @AnyDefs
+ annotations are used.
@Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )
@AnyMetaDef(
@@ -3638,74 +3742,20 @@ alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references M
Queries
Since Hibernate has more features on named queries than the one
- defined in the EJB3 specification,
+ defined in the JPA specification,
@org.hibernate.annotations.NamedQuery,
@org.hibernate.annotations.NamedQueries,
@org.hibernate.annotations.NamedNativeQuery and
@@ -4336,8 +4240,6 @@ public interface Cuisine {
@Tuplizer(impl = DynamicComponentTuplizer.class)
public Country getCountry();
public void setCountry(Country country);
-
-
}
diff --git a/annotations/src/main/java/org/hibernate/annotations/AccessType.java b/annotations/src/main/java/org/hibernate/annotations/AccessType.java
index 5a2037e318..833717fa56 100644
--- a/annotations/src/main/java/org/hibernate/annotations/AccessType.java
+++ b/annotations/src/main/java/org/hibernate/annotations/AccessType.java
@@ -34,6 +34,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Property Access type
*
+ * Prefer the standard {@link javax.persistence.Access} annotation
+ *
* @author Emmanuel Bernard
*/
@Target({ TYPE, METHOD, FIELD })
diff --git a/annotations/src/main/java/org/hibernate/annotations/CascadeType.java b/annotations/src/main/java/org/hibernate/annotations/CascadeType.java
index d3faa10b71..0fb831c5fa 100644
--- a/annotations/src/main/java/org/hibernate/annotations/CascadeType.java
+++ b/annotations/src/main/java/org/hibernate/annotations/CascadeType.java
@@ -35,9 +35,11 @@ public enum CascadeType {
DELETE,
SAVE_UPDATE,
REPLICATE,
+ /** @deprecated use @OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) */
+ @Deprecated
DELETE_ORPHAN,
LOCK,
- /** @deprecated use DETACH */
+ /** @deprecated use javax.persistence.CascadeType.DETACH */
@Deprecated
EVICT,
DETACH
diff --git a/annotations/src/main/java/org/hibernate/annotations/CollectionOfElements.java b/annotations/src/main/java/org/hibernate/annotations/CollectionOfElements.java
index ba0e68f23c..2b873aa93f 100644
--- a/annotations/src/main/java/org/hibernate/annotations/CollectionOfElements.java
+++ b/annotations/src/main/java/org/hibernate/annotations/CollectionOfElements.java
@@ -35,10 +35,12 @@ import static javax.persistence.FetchType.LAZY;
* Annotation used to mark a collection as a collection of elements or
* a collection of embedded objects
*
+ * @deprecated use @ElementCollection
* @author Emmanuel Bernard
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
+@Deprecated
public @interface CollectionOfElements {
/**
* Represent the element class in the collection
diff --git a/annotations/src/main/java/org/hibernate/annotations/IndexColumn.java b/annotations/src/main/java/org/hibernate/annotations/IndexColumn.java
index 4bd70d40f9..9a639e06cc 100644
--- a/annotations/src/main/java/org/hibernate/annotations/IndexColumn.java
+++ b/annotations/src/main/java/org/hibernate/annotations/IndexColumn.java
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
/**
* Describe an index column of a List
+ * Prefer the standard {@link javax.persistence.OrderColumn} annotation
*
* @author Matthew Inger
*/