Monday, 7 November 2022

Hibernate6: quick guide to value types

Value type represents a piece of data in the entity, which do not define its own life cycle.

 

Value types are categorized into three categories.

a.   Basic types

b.   Embeddable types

c.    Collection types

 

Basic types

A basic type is a mapping between a Java type and a single database column.

 

Following list describes the basic types.

a.   Primitive types like byte, short, int, long, float, double, boolean and char.

b.   Primitive wrappers like Byte, Short, Integer, Long, Float, Double, Boolean and Character

c.    String type

d.   Arbitrary-precision numeric types like BigInteger and BigDecimal

e.   Date/time types java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime, java.time.OffsetDateTime, java.time.Instant, java.util.Date, java.util.Calendar,      

f.     java.sql.Date, java.sql.Time, java.sql.Timestamp.

g.   Byte and character arrays:     byte[] or Byte[], char[] or Character[]

h.   Java enumerated types: Any enum

i.     Serializable types: any type that implements Serializable

 

Embeddable types

An Embeddable type life cycle is bound to the parent entity type.

 

Example

@Entity
@Table(name = "contact")
public class Contact {

	@Id
	private Integer id;

	@Embedded
	private Name name;

	private Integer age;

	...........
	...........
}

 

In the above example, Name is an embedded type.

 

Collection types

Collection types specifies the collection of elements, For example, a person might have one or more communication addresses.

 

Example

@Entity
@Table(name = "person")
public class Person {

    @Id
    private Integer id;

    @Embedded
    private Name name;

    private Integer age;

    @ElementCollection
    List<Address> addresses;

    .............
    .............
}

 

In the above example

a.   id and age are basic types

b.   name is embedded type

c.    addresses is a collection + embedded type

 

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-value-types-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

 

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample.app</groupId>
    <artifactId>hibernate-value-types-demo</artifactId>
    <version>1</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <java.version>15</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

    </properties>

    <dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.4.1</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.1.2.Final</version>
        </dependency>

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>


    </dependencies>
</project>

 

Step 3: Define entity classes.

 

Address.java

 

package com.sample.app.entity;

import jakarta.persistence.Embeddable;

@Embeddable
public class Address {
    private String street;
    private String city;
    private String state;
    private String pin;
    private String country;

    public Address() {}

    public Address(String street, String city, String state, String pin, String country) {
        this.street = street;
        this.city = city;
        this.state = state;
        this.pin = pin;
        this.country = country;
    }

    public String getStreet() {
        return street;
    }

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

    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 getPin() {
        return pin;
    }

    public void setPin(String pin) {
        this.pin = pin;
    }

    public String getCountry() {
        return country;
    }

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

}

 

Name.java

package com.sample.app.entity;

import jakarta.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;
    }

}

Person.java

package com.sample.app.entity;

import java.util.List;

import jakarta.persistence.ElementCollection;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "person")
public class Person {

    @Id
    private Integer id;

    @Embedded
    private Name name;

    private Integer age;

    @ElementCollection
    List<Address> addresses;

    public Person(Integer id, Name name, Integer age, List<Address> addresses) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.addresses = addresses;
    }

    public Integer getId() {
        return id;
    }

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

    public Name getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

}

Step 4: Create hibernate.cfg.xml file under src/main/resources folder.

 

hibernate.cfg.xml

<?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://127.0.0.1:5432/test</property>
        <property name="connection.username">postgres</property>
        <property name="connection.password">postgres</property>

        <!-- Enable the logging of all the generated SQL statements to the console -->
        <property name="show_sql">true</property>

        <!-- Format the generated SQL statement to make it more readable, -->
        <property name="format_sql">true</property>

        <!-- Hibernate will put comments inside all generated SQL statements to 
            hint what’s the generated SQL trying to do -->
        <property name="use_sql_comments">false</property>

        <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create</property>

        <!-- mappings for annotated classes -->
        <mapping class="com.sample.app.entity.Person" />
        <mapping class="com.sample.app.entity.Address" />

    </session-factory>

</hibernate-configuration>

Step 5: Define main application class.

 

App.java

package com.sample.app;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import com.sample.app.entity.Address;
import com.sample.app.entity.Name;
import com.sample.app.entity.Person;

public class App {
    private static final SessionFactory SESSION_FACTORY = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {

            final StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                    .configure("hibernate.cfg.xml").build();

            final Metadata metaData = new MetadataSources(standardRegistry).getMetadataBuilder().build();

            return metaData.getSessionFactoryBuilder().build();

        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }

    }

    public static void main(final String args[]) throws ClassNotFoundException, IOException, URISyntaxException {

        final List<Address> person1Addresses = Arrays.asList(
                new Address("Chowdeswari Street", "Bangalore", "Karnataka", "12345", "India"),
                new Address("Auto Nagar", "Vijayawada", "Andhra Pradesh", "234567", "India"));

        final List<Address> person2Addresses = Arrays.asList(
                new Address("Panchayat street", "Chennai", "Tamilanadu", "345678", "India"),
                new Address("Gandhi Nagar", "Hyderabad", "Telangana", "456789", "India"));

        final Person person1 = new Person(1, new Name("Krishna", null, "G"), 34, person1Addresses);
        final Person person2 = new Person(2, new Name("Ram", "krishna", "Geeta"), 39, person2Addresses);

        try (final Session session = SESSION_FACTORY.openSession()) {
            session.beginTransaction();
            session.persist(person1);
            session.persist(person2);
            session.getTransaction().commit();
        }

    }
}

Total project structure looks like below.

 

 


 

Run App.java, you will see below messages in the console.

Aug 09, 2022 2:21:54 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:postgresql://127.0.0.1:5432/test]
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Aug 09, 2022 2:21:55 PM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.Person (class must be instantiated by Interceptor)
Hibernate: 
    
    alter table if exists Person_addresses 
       drop constraint if exists FK8jussa4njj2adfimtdu6l87k6
Aug 09, 2022 2:21:55 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@2d55e826] 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.
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 0, SQLState: 00000
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: relation "person_addresses" does not exist, skipping
Hibernate: 
    
    drop table if exists person cascade
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 0, SQLState: 00000
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: table "person" does not exist, skipping
Hibernate: 
    
    drop table if exists Person_addresses cascade
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 0, SQLState: 00000
Aug 09, 2022 2:21:55 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: table "person_addresses" does not exist, skipping
Hibernate: 
    
    create table person (
       id integer not null,
        age integer,
        firstName varchar(255),
        lastName varchar(255),
        middleName varchar(255),
        primary key (id)
    )
Aug 09, 2022 2:21:55 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@75e09567] 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.
Hibernate: 
    
    create table Person_addresses (
       Person_id integer not null,
        city varchar(255),
        country varchar(255),
        pin varchar(255),
        state varchar(255),
        street varchar(255)
    )
Hibernate: 
    
    alter table if exists Person_addresses 
       add constraint FK8jussa4njj2adfimtdu6l87k6 
       foreign key (Person_id) 
       references person
Aug 09, 2022 2:21:55 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: 
    insert 
    into
        person
        (age, firstName, lastName, middleName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        person
        (age, firstName, lastName, middleName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        Person_addresses
        (Person_id, city, country, pin, state, street) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        Person_addresses
        (Person_id, city, country, pin, state, street) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        Person_addresses
        (Person_id, city, country, pin, state, street) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        Person_addresses
        (Person_id, city, country, pin, state, street) 
    values
        (?, ?, ?, ?, ?, ?)

 

Let’s query PostgreSQL to confirm the same.

test=# \d
              List of relations
 Schema |       Name       | Type  |  Owner   
--------+------------------+-------+----------
 public | person           | table | postgres
 public | person_addresses | table | postgres
(2 rows)

test=# 
test=# SELECT * FROM person;
 id | age | firstname | lastname | middlename 
----+-----+-----------+----------+------------
  1 |  34 | Krishna   | G        | 
  2 |  39 | Ram       | Geeta    | krishna
(2 rows)

test=# 
test=# SELECT * FROM person_addresses;
 person_id |    city    | country |  pin   |     state      |       street       
-----------+------------+---------+--------+----------------+--------------------
         1 | Bangalore  | India   | 12345  | Karnataka      | Chowdeswari Street
         1 | Vijayawada | India   | 234567 | Andhra Pradesh | Auto Nagar
         2 | Chennai    | India   | 345678 | Tamilanadu     | Panchayat street
         2 | Hyderabad  | India   | 456789 | Telangana      | Gandhi Nagar
(4 rows)

test=# 
test=# \d+ person
                                                   Table "public.person"
   Column   |          Type          | Collation | Nullable | Default | Storage  | Compression | Stats target | Description 
------------+------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
 id         | integer                |           | not null |         | plain    |             |              | 
 age        | integer                |           |          |         | plain    |             |              | 
 firstname  | character varying(255) |           |          |         | extended |             |              | 
 lastname   | character varying(255) |           |          |         | extended |             |              | 
 middlename | character varying(255) |           |          |         | extended |             |              | 
Indexes:
    "person_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "person_addresses" CONSTRAINT "fk8jussa4njj2adfimtdu6l87k6" FOREIGN KEY (person_id) REFERENCES person(id)
Access method: heap

test=# 
test=# \d+ person_addresses;
                                              Table "public.person_addresses"
  Column   |          Type          | Collation | Nullable | Default | Storage  | Compression | Stats target | Description 
-----------+------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
 person_id | integer                |           | not null |         | plain    |             |              | 
 city      | character varying(255) |           |          |         | extended |             |              | 
 country   | character varying(255) |           |          |         | extended |             |              | 
 pin       | character varying(255) |           |          |         | extended |             |              | 
 state     | character varying(255) |           |          |         | extended |             |              | 
 street    | character varying(255) |           |          |         | extended |             |              | 
Foreign-key constraints:
    "fk8jussa4njj2adfimtdu6l87k6" FOREIGN KEY (person_id) REFERENCES person(id)
Access method: heap

 

You can download this application from this link.


 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment