In chapter the section called “Typed relation (XML only)” we explained a typed relation. This approach is not possible with annotation mapping. There are two alternatives: First, TutorialReader has two fields billing_address_id, delivery_address_id. If you add a billing address to the reader, you set the type in ReaderAddress manually to “billing". Second, you map BillingAddress, DeliveryAddress and ReaderAddress as a inheritance structure. This approach is shown below: A tutorial reader has two addresses, a billing and a delivery address. Only these address types are allowed. Full source code is provided in the package: de.laliluna.relation.typed
| Classes | Tables |
|---|---|
|
|
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
...... snip ..........
@Entity
public class TutorialReader implements Serializable{
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="billing_address_id")
private BillingAddress billingAddress;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="delivery_address_id")
private DeliveryAddress deliveryAddress;The ReaderAddress includes all common properties:
import java.io.Serializable;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.SequenceGenerator;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
public class ReaderAddress implements Serializable {
@Id
@SequenceGenerator(name = "readeraddress_seq",
sequenceName = "readeraddress_id_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="readeraddress_seq")
private Integer id;
private String address;
private String city;@Inheritance(strategy=InheritanceType.SINGLE_TABLE) defines the inheritance strategy. All addresses will be kept in one table. The different addresses can be identified by a discriminator column. A discriminator column holds the type of the address. @DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
Deliveryaddress and BillingAddress are fairly short.
@Entity
public class BillingAddress extends ReaderAddress {
public BillingAddress() {
super();
}
public BillingAddress(Integer id, String address, String city) {
super(id,address,city);
}
private static final long serialVersionUID = 3313063223421102585L;
}import javax.persistence.Entity;
@Entity
public class DeliveryAddress extends ReaderAddress {
private static final long serialVersionUID = 8902940839248062796L;
public DeliveryAddress(){
super();
}
public DeliveryAddress(Integer id, String address, String city) {
super(id,address,city);
}
}The following tables are generated:
CREATE TABLE ttutorialreader
(
id int4 NOT NULL,
name varchar(255),
billingaddress_fk int4,
deliveryaddress_fk int4,
PRIMARY KEY (id),
FOREIGN KEY (billing_address_id)
REFERENCES annotation.readeraddress (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
FOREIGN KEY (delivery_address_id)
REFERENCES annotation.readeraddress (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
) ;
CREATE TABLE readeraddress
(
"type" varchar(31) NOT NULL,
id int4 NOT NULL,
address varchar(255),
city varchar(255),
PRIMARY KEY (id)
)Samples of use:
/* create and set relation */
TutorialReader reader = new TutorialReader();
reader.setName("Sebastian");
BillingAddress billing = new BillingAddress(null, "Alte Landstrasse",
"Frankfurt");
DeliveryAddress delivery = new DeliveryAddress(null, "Neue Landstrasse",
"Frankfurt");
reader.setBillingAddress(billing);
reader.setDeliveryAddress(delivery);
session.save(reader);
/* select all billing addresses */
List list = session.createQuery("from BillingAddress").list();
/* select tutorial reader with billing address in Frankfurt */
List list = session.createQuery("from TutorialReader r where
r.billingAddress.address='Alte Landstrasse'").list();