天天看點

@PrimaryKeyJoinColumn and mappedBy

1 ANNOTATIONS

1.1 @PrimaryKeyJoinColumn and mappedBy

1.1.1 Note

@PrimaryKeyJoinColumn is an annotation, while mappedBy is only an attribute of the @OneToOne, @OneToMany, @ManyToOne and @ManyToMany

1.1.2 Reference URL

The following material reference from section “2.2.5.1 One-to-one” at

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html

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 (note that this FK column in the database should be constrained unique to simulate one-to-one multiplicity), or a association table is used to store the link between the 2 entities (a unique constraint has to be defined on each fk to ensure the one to one multiplicity).

1.1.3 @PrimaryKeyJoinColumn

First, we map a real one-to-one association using shared primary keys:

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

}

The @PrimaryKeyJoinColumn annotation does say that the primary key of the entity is used as the foreign key value to the associated entity.

Comments: the primary key is in Heart, and the associated entity is Body who has a foreign key referencing the primary key of Heart.

1.1.4 mappedBy attribute

In the following example, the associated entities are linked through an explicit foreign key column:

@Entity

public class Customer implements Serializable {

@OneToOne(cascade = CascadeType.ALL)

@JoinColumn(name="passport_fk")

public Passport getPassport() {

...

}

@Entity

public class Passport implements Serializable {

@OneToOne(mappedBy = "passport")

public Customer getOwner() {

...

}

A Customer is linked to a Passport, with a foreign key column named passport_fk in the Customer table. The join column is declared with the @JoinColumn annotation which looks like the @Column annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join. Note that when using referencedColumnName to a non primary key column, the associated class has to be Serializable. Also note that the referencedColumnName to a non primary key column has to be mapped to a property having a single column (other cases might not work).

The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the association on the owner side. In our case, this is passport. As you can see, you don't have to (must not) declare the join column since it has already been declared on the owner’s side.

Comments: the owner side is Customer (@JoinColumn is defined in Customer) who will be responsible for the association column update, and mappedBy will be used in non-owner side, the value of mappedBy is the property name of the association on the owner side. In the above example, the name of the association on the owner side is “passport” (Customer has a getter method: getPassport).

If no @JoinColumn is declared on the owner side, the defaults apply. A join column(s) will be created in the owner table and its name will be the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column(s) in the owned side. In this example passport_id because the property name is passport and the column id of Passport is id.

The third possibility (using an association table) is quite exotic.

@Entity

public class Customer implements Serializable {

@OneToOne(cascade = CascadeType.ALL)

@JoinTable(name = "CustomerPassports",

joinColumns = @JoinColumn(name="customer_fk"),

inverseJoinColumns = @JoinColumn(name="passport_fk")

)

public Passport getPassport() {

...

}

@Entity

public class Passport implements Serializable {

@OneToOne(mappedBy = "passport")

public Customer getOwner() {

...

}

A Customer is linked to a Passport through a association table named CustomerPassports ; this association table has a foreign key column named passport_fk pointing to the Passport table (materialized by the inverseJoinColumn, and a foreign key column named customer_fk pointing to the Customer table materialized by the joinColumns attribute.

You must declare the join table name and the join columns explicitly in such a mapping.

繼續閱讀