@Entity @Table(name="T_CUSTOMER") public class Customer { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="CUST_ID") private int id; @Column(name="CUST_NAME") private String name; @OneToOne private Address address; } @Entity @Table(name="T_ADDRESS") public class Address { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="ADDR_ID") private int id; @Column(name="STREET") private String street; @Column(name="POSTCODE") private String postcode; }
Domain model
T_CUSTOMER.ADDRESS_ADDR_ID is the foreign key referenced to T_ADDRESS.ADDR_ID
ADDRESS_ADDR_ID is the default foreign key column name. It is derived from class name + ‘_’ + primary key name (‘ADDRESS’ + ‘_’+’ADDR_ID’)
Since by default, no operations are cascaded, Address entity needs to be saved before Customer entity does.
@PersistenceContext(unitName="unit") private EntityManager em; public void save(){ Address address = new Address("10 test st", "2912"); Customer customer = new Customer("Sun", address); //Save address to database em.save(address); //Save customer to database em.save(customer); System.out.println("Customer saved"); }
The result:
T_CUSTOMER
T_ADDRESS
Add cascade attribute
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) private Address address;
Now Address entity does not need to be saved before Customer entity does.
public void save(){ Address address = new Address("10 test st", "2912"); Customer customer = new Customer("Sun", address); //Save customer to database em.save(customer); System.out.println("Customer saved"); }
Same for update and delete.
Specify whether association is optional, fetch type
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, optional=false, fetch=FetchType.EAGER) private Address address;
Default value of optional attribute is true
Default value of fetch attribute is EAGER
Now if trying to save a customer without setting his address, an exception will be thrown.
@PersistenceContext(unitName="unit") private EntityManager em; public void save(){ Address address = new Address("10 test st", "2912"); Customer customer = new Customer("Sun", address); //Save customer to database em.save(customer); System.out.println("Customer saved"); }
Specify foreign key column name
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, optional=false, fetch=FetchType.EAGER) @JoinColumn(name="F_ADDR_ID", referencedColumnName="ADDR_ID") private Address address;
Domain model
The name attribute of @JoinColumn (‘F_ADDR_ID’) specifies the foreign key column name.
The referenceColumnName attribute of @JoinColumn (‘ADDR_ID’) specifies the primary key of the table referenced to. It can be omitted.
One-to-one bidirectional mapping
@Entity @Table(name="T_CUSTOMER") public class Customer { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="CUST_ID") private int id; @Column(name="CUST_NAME") private String name; @OneToOne(cascade={CascadeType.ALL}, optional=false) @JoinColumn(name="F_ADDR_ID") private Address address; } @Entity @Table(name="T_ADDRESS") public class Address { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="ADDR_ID") private int id; @Column(name="STREET") private String street; @Column(name="POSTCODE") private String postcode; @OneToOne(mappedBy="address") private Customer customer; }
Domain model
Same as unidirectional mapping
@PersistenceContext(unitName="unit") private EntityManager em; public void save(){ Address address = new Address("10 test st", "2912"); Customer customer = new Customer("Sun", address); address.setCustomer(customer); //Save customer to database em.save(customer); System.out.println("Customer saved"); }