Issue
I am learning Spring, Hibernate and PostgreSQL. I have an entity that has the field of the timestamp. A database column of this timestamp is called datecreated
.
This timestamp should be generated automatically but is not. While inserting a record, null value is generated only, instead of the date.
I tried many combination of solutions that are on internet, but I not succeeded. I tried this:
@CreationTimestamp
private Date dateCreated;
@CreationTimestamp
@Column
private Date dateCreated;
@CreationTimestamp
@Column
private Date dateCreated = new Date();
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column
private Date dateCreated = new Date();
@Temporal(TemporalType.TIMESTAMP)
@Column
private Date dateCreated = new Date();
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date dateCreated = new Date();
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date dateCreated = new Date();
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date dateCreated;
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date dateCreated;
@PrePersist
protected void onCreate() {
dateCreated = new Date();
}
How to make it generate the timestamps? Here you are a project files Image.java model, pom.xml, import.sql ddl, hibernate.cfg.xml files:
Image.java
package com.howtodoinjava.demo.spring.domain;
import javax.persistence.*;
import java.util.Date;
import org.hibernate.annotations.CreationTimestamp;
@Entity
@Table(name = "images")
public class Image {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 300)
private String title;
@Column(nullable = false)
private String url;
@Column(nullable = false)
private String author;
@CreationTimestamp
@Column
private Date dateCreated = new Date();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getDate() {
return dateCreated;
}
public void setDate(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Image() {}
public Image(Long id, String title, String url, String author) {
this.id = id;
this.title = title;
this.url = url;
this.author = author;
}
@Override
public String toString() {
return "Post{" +
"id=" + id +
", title='" + title + '\'' +
", url='" + url + '\'' +
", author=" + author +
", date=" + dateCreated +
'}';
}
}
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bitMiners</groupId>
<artifactId>pdf-app</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<aspect.version>1.9.2</aspect.version>
<jackson.version>2.9.8</jackson.version>
<hibernate.version>5.4.2.Final</hibernate.version>
<hibernate.validator.version>6.0.13.Final</hibernate.validator.version>
<c3p0.version>0.9.5.2</c3p0.version>
</properties>
<dependencies>
<!-- servlets and jps -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-extras</artifactId>
<version>3.0.8</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>jboss</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<!--hibernate-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Hibernate-C3P0 Integration -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<!-- for rest services -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- For Aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspect.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspect.version}</version>
</dependency>
<!-- To Send Email -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--logging-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
</dependencies>
<build>
<!-- To define the plugin version in your parent POM -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- To use the plugin goals in your POM or parent POM -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
import.sql
This file is placed in a path: src/main/resources/import.sql and it is automatically executed when running the project. This is taken from a tutorial https://dzone.com/articles/spring-security-5-form-login-with-database-provide
-- ...
INSERT INTO images (title, url, author) VALUES ('lanszaft', 'https://i.imgur.com/sZ64fVI.jpg', 'Oskar Kamiński');
INSERT INTO images (title, url, author) VALUES ('kobieta w kapeluszu', 'https://i.imgur.com/spMsvHe.png', 'Pablo Picasso');
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>
<property name="hibernate.archive.autodetection">class,hbm</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/postgres</property> <!-- BD Mane -->
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.username">user32</property>
<property name="hibernate.connection.password">pa$$word</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL95Dialect</property>
<property name="hibernate.connection.pool.size">1</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.enable_lazy_load_no_trans">true</property>
<property name="hibernate.jdbc.lob.non_contextual_creation">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">150</property>
<mapping class="com.howtodoinjava.demo.spring.domain.User"/>
<mapping class="com.howtodoinjava.demo.spring.domain.Authority"/>
<mapping class="com.howtodoinjava.demo.spring.domain.AuthorityType"/>
<mapping class="com.howtodoinjava.demo.spring.domain.Image"/>
</session-factory>
</hibernate-configuration>
Solution
The prePersist and other @createTimeStamp hooks works if you are making inserts from within the application by using the JPA or native hibernate methods. If you simply run inserts from outside your application context, there is no way hibernate would come to know what DMLs are running and hence the hooks will never be called. If you want that even from outside when you run the inserts, the timestamp for create should auto populate, you would need to add table level DDL instructions.
Eg: ALTER TABLE mytable ALTER COLUMN datecreated SET DEFAULT now();
Now as to auto DDL ability of hibernate, the xml property <property name="hibernate.hbm2ddl.auto">create</property>
generates DDL from entity definitions but not DMLs. So, you can also embed the DEFAULT timestamp value in column definition of the concerned entity as so or similar:
@Column(name="datecreated", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
This will ensure that when the table is created, the definition is applied using the auto DDL property of hibernate settings.
Hope this clarifies
Answered By - Ed Bighands
Answer Checked By - Mildred Charles (JavaFixing Admin)