Showing posts with label double. Show all posts
Showing posts with label double. Show all posts

Wednesday, 16 November 2022

Hibernate 6: Double and Float values mapping

Depending on the capabilities of the database, Hibernate maps Double values to the following JDBC types

a.   DOUBLE,

b.   FLOAT,

c.    REAL or

d.   NUMERIC

 

Depending on the capabilities of the database, Hibernate maps Float values to the following JDBC types

a.   FLOAT,

b.   REAL or

c.    NUMERIC

 

For example, 

@Entity
@Table(name = "double_float_demo")
public class DoubleFloatDemo {

    @Id
    private Integer id;

    private Double d;

    private Float f;

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

 

Hibernate generates following DDL for above entity class.

create table double_float_demo (
    id integer not null,
    d float(53),
    f float4,
    primary key (id)
)

 

PostgreSQL accepts float(1) to float(24) as selecting the real type, while float(25) to float(53) to select double precision.

 

 

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-double-float-type-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-double-float-type-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 DoubleFloatDemo entity class.

 

DoubleFloatDemo.java

package com.sample.app.entity;

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

@Entity
@Table(name = "double_float_demo")
public class DoubleFloatDemo {

    @Id
    private Integer id;

    private Double d;

    private Float f;

    public DoubleFloatDemo(Integer id, Double d, Float f) {
        this.id = id;
        this.d = d;
        this.f = f;
    }

    public Integer getId() {
        return id;
    }

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

    public Double getD() {
        return d;
    }

    public void setD(Double d) {
        this.d = d;
    }

    public Float getF() {
        return f;
    }

    public void setF(Float f) {
        this.f = f;
    }

}

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>

        <property name="hbm2ddl.auto">update</property>

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

    </session-factory>

</hibernate-configuration>

Step 5: Define main application class.

 

App.java

package com.sample.app;

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.DoubleFloatDemo;

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[]) {

        DoubleFloatDemo p1 = new DoubleFloatDemo(1, 2.2, 3.3f);

        try (final Session session = SESSION_FACTORY.openSession()) {
            session.beginTransaction();

            session.persist(p1);

            session.getTransaction().commit();

        }

    }
}

Total project structure looks like below.



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

Aug 16, 2022 11:27:32 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:postgresql://127.0.0.1:5432/test]
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
Aug 16, 2022 11:27:33 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Aug 16, 2022 11:27:33 AM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.DoubleFloatDemo (class must be instantiated by Interceptor)
Aug 16, 2022 11:27:33 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@26fb4d06] 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 double_float_demo (
       id integer not null,
        d float(53),
        f float4,
        primary key (id)
    )
Aug 16, 2022 11:27:33 AM 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
        double_float_demo
        (d, f, id) 
    values
        (?, ?, ?)

Query PostgreSQL to confirm the table ddl and content.

test=# \d+ double_float_demo
                                        Table "public.double_float_demo"
 Column |       Type       | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
--------+------------------+-----------+----------+---------+---------+-------------+--------------+-------------
 id     | integer          |           | not null |         | plain   |             |              | 
 d      | double precision |           |          |         | plain   |             |              | 
 f      | real             |           |          |         | plain   |             |              | 
Indexes:
    "double_float_demo_pkey" PRIMARY KEY, btree (id)
Access method: heap

test=# 
test=# 
test=# SELECT * FROM double_float_demo;
 id |  d  |  f  
----+-----+-----
  1 | 2.2 | 3.3
(1 row)

You can download the complete working application from this link.


Previous                                                    Next                                                    Home

Wednesday, 20 July 2022

Why to do explicit type casting from double to float conversion?

Here is the scenario, consider the following statement.

byte b1 = 10;

 

literal '5' is of type int and can be fit into a variable of type byte. In this example compiler will do implicit type casting from int to byte.

 

Now consider the below statement.

float fl = 10.1;

 

literal '10.0' is of type double, and can be fit into a variable of type float, but you will get a compiler error why?

 

Let’s talk about int to byte conversion first

byte b1 = 10;

In the above example, java compiler knows that the value 10 is entirely fit into a byte variable (byte can store from -128 to 127), there is no loss of information here.

 


NumberConversion1.java

public class NumberConversion1 {
    
    public static void main(String[] args) {
        byte b1 = 10;
        
        System.out.println("b1 : " + b1);
    }

}

Compile and run above application.

$javac NumberConversion1.java 
$
$java NumberConversion1
b1 : 10

Let’s consider below statement.

byte b1 = 128;

As 128 is not fit into a byte variable (-128 to 127), there is a loss of information here. When you try to compile the code, you will get compiler error.

 

NumberConversion2.java

public class NumberConversion2 {
    
    public static void main(String[] args) {
        byte b1 = 128;
        
        System.out.println("b1 : " + b1);
    }

}

Try to compile above program, you will get the following error message.

$javac NumberConversion2.java 
NumberConversion2.java:4: error: incompatible types: possible lossy conversion from int to byte
        byte b1 = 128;
                  ^
1 error

Same is the case with following statement also.

float f1 = 10.1;

10.1 is a double which uses a 64-bit value and approximates 10.1 more accurately than 10.1f which only uses a 32-bit to store the data. Since there is a possible lossy conversion here, compiler throw the error.

 

NumberConversion3.java

public class NumberConversion3 {
    
    public static void main(String[] args) {
        float f1 = 10.1;
        
        System.out.println("f1 : " + f1);
    }

}

Try to compile above program, you will get below error.

$javac NumberConversion3.java 
NumberConversion3.java:4: error: incompatible types: possible lossy conversion from double to float
        float f1 = 10.1;
                   ^
1 error

10.1 is not same as 10.1f

Since 10.1 is a double which uses a 64-bit value and approximates 10.1 more accurately than 10.1f which only uses a 32-bit. Since there is a possible lossy conversion here, compiler throw the error.

 

Let’s confirm the same with below example.

 

NumberConversion4.java

public class NumberConversion4 {

    public static void main(String[] args) {
        if (10.1f == 10.1) {
            System.out.println("Both are same");
        } else {
            System.out.println("Both are not same");
        }
        
        System.out.println("(10.1 - 10.1f) = " + (10.1 - 10.1f));

    }

}

Output

Both are not same
(10.1 - 10.1f) = -3.8146972691777137E-7

Use explicit casting to convert a double to float value, here we are conveying to the compiler that I am agreeing to the possible loss of information.

float f1 = (float)10.1;

 

You may like

Interview Questions

What happen to the threads when main method complete execution

Why System.out.println() is not throwing NullPointerException on null references?

Why should we restrict direct access to instance properties?

Closeable vs AutoCloseable in Java

What is the behaviour of static final method in Java?

How to check two double values for equality?