Training, Workshops, Softwareentwicklung

Hibernate Tutorial

Bidirektionales OneToOne

Bei einer bidirektionalen OneToOne Beziehung bildet man sowohl im Customer die Beziehung zur Registration ab, als auch umgekehrt.

Wichtig ist hier, das der Fremdschlüssel in der Registration abgebildet wird.

Das Datenbankschema sieht dann so aus:

06 09 dbschema

Das bidirektionale Mapping in den Entities sieht so aus:

Mapping Customer
@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cust_gen")
    @SequenceGenerator(name = "cust_gen", sequenceName = "customer_seq", allocationSize = 1)
    private Long id;
    // getter / setter omitted
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer") (1)
    private Registration registration;
1 mappedBy macht die andere Seite zum Owner der Beziehung.

Die Registration legt die @JoinColumn fest:

Mapping Registration
@Entity
public class Registration {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "reg_gen")
    @SequenceGenerator(name = "reg_gen", sequenceName = "registration_seq", allocationSize = 1)
    private Long id;
    // getter / setter omitted
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id") (1)
    private Customer customer;

Wir müssen darauf achten, den Customer in der Registration richtig zu setzen, da diese der Owner der Beziehung ist:

Setup
Customer customer = new Customer();
customer.setFirstname("Buck");
customer.setLastname("Rogers");

Registration registration = new Registration();
registration.setRegistrationNo("1234");

customer.setRegistration(registration);
registration.setCustomer(customer); (1)

withTransaction(em, () ->
        em.persist(customer)
);
1 Der Customer muss in die Registration eingetragen werden!

Auch hier haben wir durch das Lazy Loading eventuell ein n+1 Select Problem:

Test
doInHibernate(em -> {

    TypedQuery<Customer> query = em.createQuery("SELECT c FROM Customer c", Customer.class);
    Customer customer = query.getSingleResult();

    Registration registration = customer.getRegistration(); (1)

    assertEquals("1234", registration.getRegistrationNo());
});
assertSelectCount(2); (2)
1 Beim Zugriff auf die Registration erfolgt ein zusätzlicher Datenbankzugriff
2 Wir sehen zwei Selects!