Embedding Objects using Hibernate
In the previous tutorials, we have learned various things about Hibernate, a list of them is shown below.
- Brief introduction
- Setting up hibernate
- Getting started with Hibernate API – JPA
- Elaboration of Hibernate configuration file
- Explanation of Hibernate Annotations
- Create/Read Operation on a database with Hibernate
- Use of primary keys with hibernate.
The example that we have taken allows us to store class level variable as table columns in the database. These class level variables are simple with data types like strings , date etc. We know that in classes we can have other objects as class level variables we can also have arrays and collections as a class level variables, now the question arises. How will we store these complex variables in the database with hibernate? In this tutorial and some other upcoming tutorials, we will try to find the answer to this question.
Example Embedding Objects
Let’s try to understand with the example, We will create a new class named “Address.java” it will have four class level variables “Street, City , Distinct, Country”. In the previous example, we have the user class with name and Id as class level variables. In this example, we will add this address class object in our User Class as a class level variable with name and ID and try to save it.
When dealing with hibernate we see two types of objects Value Objects and Entity. Before we move further we have to know the difference between them.
Entity
It is a class that needs to be saved as a separate table in the database. An Independent class that has its own meaning is called as an Entity. Data present inside the entity provides the meaning of itself.
Value Objects
It is an Object that has data and needs to be saved in the database but doesn’t have to mean as of itself. It is a supportive object that adds meaning to another object.
@Embeddable and @Embedded
In our Example we have an Address object, this object independently doesn’t have a meaning. We have to use its object with another entity to complete its meaning. The purpose of this object is to provide value to the user class. Steps for creating and editing the address class is as follows
- Create a new java class named Address.
- Define for class level variables/fields in the created class all with data type string and access modifiers set as private.
- Generate gets and setters for these fields.
- We will use annotation “@Embeddable” with this Address class to tell hibernate that its object needs to be embedded in somewhere else.
- Hibernate provides this functionality in javax.persistance.Embeddable
Address.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package org.beginnersheap.uzair.dto; import javax.persistence.Embeddable; @Embeddable public class Address { private String Street; private String City ; private String District; private String Country; public String getStreet() { return Street; } public void setStreet(String street) { Street = street; } public String getCity() { return City; } public void setCity(String city) { City = city; } public String getDistrict() { return District; } public void setDistrict(String district) { District = district; } public String getCountry() { return Country; } public void setCountry(String country) { Country = country; } } |
Now In the User Class, we will perform following updates.
- We will create an object of this Address class
- Set its access modifier to private.
- Generate getters and setters for the address object. Here we can also use “@Embedded” annotation with this address object to tell hibernate that t needs to be embedded. If we have used @ Embeddable in the address Class then this annotation is not mandatory.
UserDetails.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package org.beginnersheap.uzair.dto; import java.util.Date; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Table; import javax.persistence.Id; @Entity @Table (name="NewTableName") public class UserDetails { @Id @GeneratedValue (strategy= GenerationType.AUTO) private int userId; private String userName; @Embedded private Address addressObject;//object of the Address class public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } //getters and setters for the address object public Address getAddressObject() { return addressObject; } public void setAddressObject(Address addressObject) { this.addressObject = addressObject; } } |
Finally, in our Main class, we will add following things.
- Create an address object
- Set the value of Street, City , Distinct, Country by Using this object.
- Add this object to the user’s object that we previously have.
- Ultimately Save the user object using Session Object.
- Now we are ready to run the example.
HibernateMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package org.uzair.hibernate; import java.util.Date; import org.beginnersheap.uzair.dto.Address; import org.beginnersheap.uzair.dto.UserDetails; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateMain { public static void main(String[] args) { UserDetails objectUser = new UserDetails(); Address addressObject=new Address();// address object //Setting the values for Street, City , Distinct, Country by Using the above created object addressObject.setCity("Wah"); addressObject.setCountry("Pakistan"); addressObject.setDistrict("Rawalpindi"); addressObject.setStreet("St Four"); objectUser.setUserName("FirstUserName"); objectUser.setAddressObject(addressObject);//Add address object in the user’s object SessionFactory factory = new Configuration().configure().buildSessionFactory(); Session session = factory.openSession(); session.beginTransaction(); session.save(objectUser);// Save the user object session.getTransaction().commit(); //Reterive UserObject using Hibernate API session.close(); session = factory.openSession(); objectUser=null; session.beginTransaction(); objectUser = (UserDetails) session.get(UserDetails.class, 1); System.out.println("UserName : "+objectUser.getUserName()); System.out.println("City: "+objectUser.getAddressObject().getCity()); } } |
hibernate.cfg.xml
This file will remain the same as our previous examples.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">org.postgresql.Driver</property> <property name="connection.url">jdbc:postgresql://localhost:5432/hibernatedb</property> <property name="connection.username">postgres</property> <property name="connection.password">1234poiu</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create</property> <!-- Names the annotated entity class --> <mapping class="org.beginnersheap.uzair.dto.UserDetails"/> </session-factory> </hibernate-configuration> |
Test Run:
Right, click on HibernateMain.java click RunAs and then RunAsServer.
Console
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<strong>Hibernate: drop table if exists NewTableName cascade </strong>Oct 12, 2016 3:18:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5dd91bca] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. Oct 12, 2016 3:18:49 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning WARN: SQL Warning Code: 0, SQLState: 00000 Oct 12, 2016 3:18:49 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning WARN: table "newtablename" does not exist, skipping <strong>Hibernate: drop sequence if exists hibernate_sequence Hibernate: create sequence hibernate_sequence start 1 increment 1 </strong>Oct 12, 2016 3:18:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@75390459] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. <strong>Hibernate: create table NewTableName (userId int4 not null, City varchar(255), Country varchar(255), District varchar(255), Street varchar(255), userName varchar(255), primary key (userId)) </strong>Oct 12, 2016 3:18:49 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@2bd2b28e' <strong>Hibernate: select nextval ('hibernate_sequence') Hibernate: insert into NewTableName (City, Country, District, Street, userName, userId) values (?, ?, ?, ?, ?, ?) Hibernate: select userdetail0_.userId as userId1_0_0_, userdetail0_.City as City2_0_0_, userdetail0_.Country as Country3_0_0_, userdetail0_.District as District4_0_0_, userdetail0_.Street as Street5_0_0_, userdetail0_.userName as userName6_0_0_ from NewTableName userdetail0_ where userdetail0_.userId=? UserName : FirstUserName City: Wah</strong> |
Now open the pgAdmin III to view the inserted records.
We can see the record is inserted successfully.
Summary:
In this tutorial, we have accomplished following things.
- Learned about Value Objects and Entity.
- How to Embed an object within another using Hibernate.
- A Complete Example of @Embeddable and @Embedded Annotations .
Hope that you like this tutorial. Stay tuned for more upcoming tutorials. Stay Blessed!
About Author: Uzair Ahmed Khan is Technical Content Writer, Computer Software Blogger, and Software Engineer. He has a keen eye on Java Technologies and other Related Developments.