Tuesday, 8 November 2022

Hibernate 6: @Column: Specify details about this column

 

@Column annotation specify the details about this column.

 

Below table summarizes the attributes of @Column annotation.

 

Attribute

Description

Data type

name

Specify the column name. Field or property name is taken by default.

String

unique

Specify whether this column has unique key constraint or not.

boolean

nullable

Specifies whether the column take null value or not.

boolean

insertable

Specifies whether the column is included in SQL INSERT statements generated by the persistence provider.

boolean

updatable

Specifies Whether the column is included in SQL UPDATE statements generated by the persistence provider.

boolean

columnDefinition

Specifies the SQL fragment that is used when generating the DDL for the column.

String

table

Specifies the name of the table that contains the column. If absent the column is assumed to be in the primary table.

String

length

Specifies he column length. It applies only if a string-valued column is used.

int

precision

Specifies the precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.) Value must be set by developer if used when generating the DDL for the column.

int

scale

Specifies the scale for a decimal (exact numeric) column. Applies only if a decimal column is used.)

int

 

Example 1: Specifies the column 'person_name' with lenght 512 characters and apply not null constraint. 

@Column(name = "person_name", nullable = false, length = 512)
private String name;

 

Example 2: Explcitly set the type to TEXT and apply not null constraint.

@Column(columnDefinition = "TEXT NOT NULL")
private String description;

Example 3: Make sure that this column is not updatable and not null also.

@Column(name = "created_ts", nullable = false, updatable = false)
private Timestamp createdTimestamp;

Example 4: Example on precision and scale

Column(name="order_cost", updatable=false, precision=12, scale=2)
public BigDecimal getCost() { return cost; }

Precision refers to the maximum number of digits that are present in the number. For example, 12345.67 has a precision of 7. Scale refers to the maximum number of decimal places in the number. For example, 12345.67 has a scale of 2.

 

Thus the maximum allowed value for decimal(7,2) is 99999.99

 

Find the below Person entity class.

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

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "person_name", nullable = false, length = 512)
    private String name;

    private Integer age;

    @Column(columnDefinition = "TEXT NOT NULL")
    private String description;

    @CreationTimestamp
    @Column(name = "created_ts", nullable = false, updatable = false)
    private Timestamp createdTimestamp;

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

 

Above entity generates following DDL.

create table person (
    id integer not null,
    age integer,
    created_ts timestamp(6) not null,
    description TEXT NOT NULL,
    person_name varchar(512) not null,
    primary key (id)
)

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-column-annotation-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-column-annotation-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 class.

 

Person.java

package com.sample.app.entity;

import java.sql.Timestamp;

import org.hibernate.annotations.CreationTimestamp;

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

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

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "person_name", nullable = false, length = 512)
    private String name;

    private Integer age;

    @Column(columnDefinition = "TEXT NOT NULL")
    private String description;

    @CreationTimestamp
    @Column(name = "created_ts", nullable = false, updatable = false)
    private Timestamp createdTimestamp;

    public Person(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Timestamp getCreatedTimestamp() {
        return createdTimestamp;
    }

    public void setCreatedTimestamp(Timestamp createdTimestamp) {
        this.createdTimestamp = createdTimestamp;
    }

}

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" />

    </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 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.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 {

        Person person1 = new Person("Krishna", 23, "I am a traveller");
        Person person2 = new Person("Ram", 31, "blogger, Entrepreneur, content writer");

        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 console.

Aug 09, 2022 3:29:30 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 09, 2022 3:29:30 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 09, 2022 3:29:30 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Aug 09, 2022 3:29:30 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 3:29:30 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Aug 09, 2022 3:29:30 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 09, 2022 3:29:30 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
Aug 09, 2022 3:29:31 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Aug 09, 2022 3:29:31 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: 
    
    drop table if exists person cascade
Aug 09, 2022 3:29:31 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@288f173f] 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 3:29:31 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 0, SQLState: 00000
Aug 09, 2022 3:29:31 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: table "person" does not exist, skipping
Hibernate: 
    
    drop sequence if exists person_SEQ
Aug 09, 2022 3:29:31 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 0, SQLState: 00000
Aug 09, 2022 3:29:31 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: sequence "person_seq" does not exist, skipping
Hibernate: create sequence person_SEQ start with 1 increment by 50
Aug 09, 2022 3:29:31 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@2ef0dd86] 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 (
       id integer not null,
        age integer,
        created_ts timestamp(6) not null,
        description TEXT NOT NULL,
        person_name varchar(512) not null,
        primary key (id)
    )
Aug 09, 2022 3:29:31 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: 
    select
        nextval('person_SEQ')
Hibernate: 
    select
        nextval('person_SEQ')
Hibernate: 
    insert 
    into
        person
        (age, created_ts, description, person_name, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        person
        (age, created_ts, description, person_name, id) 
    values
        (?, ?, ?, ?, ?)

Query the database in PostgreSQL, you will observe that two table person, person_seq are created. ‘person_seq’ table is used to generate sequence numbers that are used in person primary key auto generation.

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

test=# 
test=# SELECT * FROM person;
 id | age |       created_ts        |              description              | person_name 
----+-----+-------------------------+---------------------------------------+-------------
  1 |  23 | 2022-08-09 15:29:31.54  | I am a traveller                      | Krishna
  2 |  31 | 2022-08-09 15:29:31.548 | blogger, Entrepreneur, content writer | Ram
(2 rows)

test=# 
test=# SELECT * FROM person_seq;
 last_value | log_cnt | is_called 
------------+---------+-----------
         51 |      31 | t
(1 row)

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    |             |              | 
 created_ts  | timestamp(6) without time zone |           | not null |         | plain    |             |              | 
 description | text                           |           | not null |         | extended |             |              | 
 person_name | character varying(512)         |           | not null |         | extended |             |              | 
Indexes:
    "person_pkey" PRIMARY KEY, btree (id)
Access method: heap

test=# 
test=# 
test=# \d+ person_seq;
                         Sequence "public.person_seq"
  Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache 
--------+-------+---------+---------------------+-----------+---------+-------
 bigint |     1 |       1 | 9223372036854775807 |        50 | no      |     1


You can download this application from this link.



Previous                                                    Next                                                    Home

No comments:

Post a Comment