Hibernate Notes (Mapping Embeddable Components)

Keywords: Attribute Database Hibernate SQL

assembly

They don't have their own identifiers, their primary key is that the entity they belong to has a mapped database identifier, and the embedded components have a separate life cycle: when they save their own entity instance, they also save the component instance, when their own entity instance is deleted, they also delete the component instance. Hibernate doesn't even need to execute any special SQL for this purpose, and all the data is in one line.
Java has no concept of composition. Classes or attributes can not be marked as components or composite lifecycle. The only difference with entities is database identifier: component classes have no independent identifier; therefore, component classes do not need identifier attributes or identifier mapping. It is a simple POJO code:

@Embeddable
public class Address {
    @NotNull
    @Column(nullable = false)
    private String street;

    @NotNull
    @Column(nullable = false, length = 5)
    private String zipcode;

    @NotNull
    @Column(nullable = false)
    private String city;

    public Address() {
    }

    public Address(String street, String zipcode, String city) {
        this.street = street;
        this.zipcode = zipcode;
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

Usage method:

@Entity
@Table(name = "t_Users")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    //Address is @Embeddable. No comment is required here.
    private Address homeAddress;

    public Long getId() {
        return id;
    }


    public Address getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(Address homeAddress) {
        this.homeAddress = homeAddress;
    }
}

Hibernate detects whether the Address class annotates with @Embeddable, street, zipcode,city columns are mapped on the t_Users table, that is, the table of the entity to which they belong.
In a more realistic scenario, a User might use different addresses for different purposes, such as a User with a home address and a billing address:

Override Embedded Properties

BilingAddress is another embedded component property of the User class, so another address must be saved in the t_Users table, which causes mapping conflicts. So far, only one address column is stored in street,zipcode,city. In the architecture, additional columns are needed to store another Address for each User row. When mapping billingAddress, the name of the column is rewritten.

@Entity
@Table(name = "t_Users")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    private Address homeAddress;
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "street",
                    column = @Column(name = "billing_street")),
            @AttributeOverride(name = "zipcode",
                    column = @Column(name = "billing_zipcode", length = 5)),
            @AttributeOverride(name = "city",
                    column = @Column(name = "billing_city"))
    })
    private Address billingAddress;

    public Address getBillingAddress() {
        return billingAddress;
    }

    public void setBillingAddress(Address billingAddress) {
        this.billingAddress = billingAddress;
    }

    public Long getId() {
        return id;
    }


    public Address getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(Address homeAddress) {
        this.homeAddress = homeAddress;
    }
}

Database Entities: t_Users


image.png

@ Attribute Overrides selectively overrides the attribute mapping of the embedded class; in this example, all three attributes are overridden and different column names are provided. Now you can store two Address instances in the t_Users table, each in a different column.
Used for components
Every @AttributeOverride for component attributes is complete: any JPA or Hibernate on overridden attributes will be ignored, which means that @Column annotations on Address classes will be ignored - - all billing_* columns can be null. (Bean validation will still recognize @NotNull annotations on component attributes; Hibernate will only override persistent annotations.)

Mapping Nested Embeddable Components

Consider the Address class and how it encapsulates address details. Instead of using a simple city string, move this detail to a new City embeddable class, code as follows:

Class City

@Embeddable
public class City {
    @NotNull
    @Column(nullable = false, length = 5)
    private String zipcode;
    @NotNull
    @Column(nullable = false)
    private String name;

    @NotNull
    @Column(nullable = false)
    private String country;

    public City() {
    }

    public City(String zipcode, String name, String country) {
        this.zipcode = zipcode;
        this.name = name;
        this.country = country;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

Class Address

@Embeddable
public class Address {
    @NotNull
    @Column(nullable = false)
    private String street;


    @NotNull
    @AttributeOverrides(
            @AttributeOverride(name = "name",
                    column = @Column(name = "city", nullable = false))
    )
    private City city;

    public Address() {
    }

    public Address(String street, City city) {
        this.street = street;
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }


    public City getCity() {
        return city;
    }

    public void setCity(City city) {
        this.city = city;
    }


}

Class User

@Entity
@Table(name = "t_Users")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    private Address homeAddress;
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "street",
                    column = @Column(name = "billing_street")),
            @AttributeOverride(name = "city.zipcode",
                    column = @Column(name = "billing_zipcode", length = 5)),
            @AttributeOverride(name = "city.name",
                    column = @Column(name = "billing_city")),
            @AttributeOverride(name = "city.country",
                    column = @Column(name = "billing_country"))
    })
    private Address billingAddress;

    public Address getBillingAddress() {
        return billingAddress;
    }

    public void setBillingAddress(Address billingAddress) {
        this.billingAddress = billingAddress;
    }

    public Long getId() {
        return id;
    }


    public Address getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(Address homeAddress) {
        this.homeAddress = homeAddress;
    }
}

Database Entities: t_Users


image.png

Attribute Overrides can be declared at any level and mapped to City columns as the name attribute of the City class does. This can be achieved using @AttributeOverride in Address (shown) or overridden in the root entity class User. Nested attributes can be referenced by. Symbols: for example, @AttributeOverride (name = city. country), column = @Column (name = billing_country)). Address's # City#name attribute is referenced.

Posted by biggieuk on Tue, 21 May 2019 12:56:46 -0700