Hibernate Component Mapping Using @Embeddable and @Embedded Annotation

In this article, we show how to embed one entity inside another entity, so they are mapped to a single table. With Hibernate we can use the @Embeddable annotation to mark a class to be eligible as an embeddable class. We can use the @Embedded annotation to embed an embeddable class. The attributes of an embedded class can be overridden using the @AttributeOverrides and the @AttributeOverride annotations. Let’s see how this works, by following a complete example.
Master in Hibernate ORM at Hibernate 5 ORM Tutorial

Technologies and tools used

  • Hibernate 5.3.7.Final
  • IDE - Eclipse Noen
  • Maven 3.5.3
  • JavaSE 1.8
  • MySQL - 8.0.13

1. Create a Simple Maven Project

Use How to Create a Simple Maven Project in Eclipse article to create simple Maven project in Eclipse IDE.

2. Project Directory Structure

The project directory structure for your reference - 

3. Add jar Dependencies to pom.xml

We use Apache Maven to manage the project's dependencies. Add the following dependencies to your projects pom.xml file.
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.javaguides.hibernate</groupId>
        <artifactId>hibernate-tutorial</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hibernate-Embaddable-example</artifactId>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.3.7.Final</version>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4. Creating an Embeddable Class using @Embeddable

Let's create Address and Name classes as Embeddable Class. The advantage of using embedded objects is that they are reusable and you can map two entities to the same database table.

Address.java

package net.javaguides.hibernate.entity;

import javax.persistence.Embeddable;

@Embeddable
public class Address {
    private String addressLine1;

    private String addressLine2;

    private String city;

    private String state;

    private String country;

    private String zipCode;

    public Address() {

    }

    public Address(String addressLine1, String addressLine2, String city, String state, String country,
        String zipCode) {
        this.addressLine1 = addressLine1;
        this.addressLine2 = addressLine2;
        this.city = city;
        this.state = state;
        this.country = country;
        this.zipCode = zipCode;
    }

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getAddressLine2() {
        return addressLine2;
    }

    public void setAddressLine2(String addressLine2) {
        this.addressLine2 = addressLine2;
    }

    public String getCity() {
        return city;
    }

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

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

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

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }
}

Name.java

package net.javaguides.hibernate.entity;

import javax.persistence.Embeddable;

@Embeddable
public class Name {
    private String firstName;

    private String middleName;

    private String lastName;

    public Name() {

    }

    public Name(String firstName, String middleName, String lastName) {
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Embedding an Embeddable object with @Embedded

We can simply embed an embeddable class using the @Embedded annotation. This class will be embedded in the same database table as the source. We can optionally override the attributes of the embedded class using the @AttributeOverrides and @AttributeOverride annotation. Let's create User class and embed Address and Name classes into it using the @Embedded annotation:
package net.javaguides.hibernate.entity;

import javax.persistence.*;

/**
 * Created by ramesh
 */
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Embedded
    private Name name;

    private String email;

    @Embedded
    @AttributeOverrides(value = {
        @AttributeOverride(name = "addressLine1", column = @Column(name = "house_number")),
        @AttributeOverride(name = "addressLine2", column = @Column(name = "street"))
    })
    private Address address;

    public User() {

    }

    public User(Name name, String email, Address address) {
        this.name = name;
        this.email = email;
        this.address = address;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Name getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

Create a Hibernate configuration file - Java Configuration

The HibernateUtil Java configuration file contains information about the database and mapping file.
Let's create a HibernateUtil file and write the following code in it.
package net.javaguides.hibernate.util;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

import net.javaguides.hibernate.entity.Student;

public class HibernateUtil {
    private static SessionFactory sessionFactory;
    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration();

                // Hibernate settings equivalent to hibernate.cfg.xml's properties
                Properties settings = new Properties();
                settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
                settings.put(Environment.URL, "jdbc:mysql://localhost:3306/hibernate_db?useSSL=false");
                settings.put(Environment.USER, "root");
                settings.put(Environment.PASS, "root");
                settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");

                settings.put(Environment.SHOW_SQL, "true");

                settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");

                settings.put(Environment.HBM2DDL_AUTO, "create-drop");

                configuration.setProperties(settings);

                configuration.addAnnotatedClass(Student.class);

                ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties()).build();

                sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sessionFactory;
    }
}

Running and Testing Embeddable Objects

When we execute the following application, a record will be added to the database.
package net.javaguides.hibernate;

import org.hibernate.Session;
import org.hibernate.Transaction;

import net.javaguides.hibernate.entity.Address;
import net.javaguides.hibernate.entity.Name;
import net.javaguides.hibernate.entity.User;
import net.javaguides.hibernate.util.HibernateUtil;

public class App {
    public static void main(String[] args) {

        Name name = new Name("Ramesh", "M", "Fadatare");
        Address address = new Address("111", "Puadroad", "Pune", "Maharastra", "India", "411038");
        User user = new User(name, "ramesh@gmail.com", address);

        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            // start a transaction
            transaction = session.beginTransaction();
            // save the student object
            session.save(user);
            // commit transaction
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
    }
}

MySQL Database Table

Output


Complete guide/tutorial to Hibernate 5 ORM at Hibernate ORM

GitHub Repository

The complete source code of this article available on my GitHub Repository - https://github.com/RameshMF/Hibernate-ORM-Tutorials

Conclusion

In this article, we have shown how to embed one entity inside another entity, so they are mapped to a single table. We have seen a complete example of using @Embeddable and @Embedded annotations to embed an embeddable class.

You can learn more about Hibernate ORM Framework at Hibernate Tutorial

References

Hibernate ORM 5.4.0.Final User Guide 

Comments