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();