Генерировать временную метку в столбце при вставке в Spring, Hibernate и PostgreSQL

#java #spring #postgresql #hibernate #auto-generate

#java #spring #postgresql #спящий режим #автогенерация

Вопрос:

Я изучаю Spring, Hibernate и PostgreSQL. У меня есть объект, который имеет поле временной метки. Вызывается столбец базы данных с этой временной меткой datecreated .

Эта временная метка должна быть сгенерирована автоматически, но это не так. При вставке записи генерируется только нулевое значение вместо даты.

Я перепробовал множество комбинаций решений, которые есть в Интернете, но мне это не удалось. Я попробовал это:


 @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();
}
  

Это то, что я получаю:
введите описание изображения здесь

Как заставить его генерировать временные метки? Здесь вы файлы проекта Image.java модель, pom.xml , import.sql ddl, hibernate.cfg.xml файлы:

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

Этот файл помещается по пути: src/main/resources/import.sql и автоматически выполняется при запуске проекта. Это взято из учебника 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>
  

Комментарии:

1. Вы имеете в виду, когда import.sql применил значение DateCreated, которого нет в таблице?

2. Как вы получили файл import.sql? это то, что генерируется в журналах при вызове persiste() или save() в вашем классе, который управляет взаимодействиями с базой данных (обычно DAO)?

3. @code_mechanic да

4. @EdBighands Этот файл является частью проекта. Проект основан на учебном пособии dzone.com/articles/… . В руководстве этот файл описан следующим образом: «3. Заполнение таблицы базы данных После определения сущностей вы можете поместить import.sql в папку resources в структуре проекта, чтобы Hibernate мог заполнять таблицы инструкциями SQL внутри».

Ответ №1:

prePersist и другие хукеры @createTimestamp работают, если вы делаете вставки из приложения с помощью JPA или собственных методов hibernate. Если вы просто запускаете вставки из-за пределов контекста вашего приложения, hibernate никак не узнает, какие DML запущены, и, следовательно, перехваты никогда не будут вызваны. Если вы хотите, чтобы даже извне, когда вы запускаете вставки, временная метка для create должна заполняться автоматически, вам нужно будет добавить инструкции DDL на уровне таблицы. Например: ALTER TABLE mytable ALTER COLUMN datecreated SET DEFAULT now();

Теперь, что касается автоматической возможности DDL в hibernate, свойство xml <property name="hibernate.hbm2ddl.auto">create</property> генерирует DDL из определений сущностей, но не DML. Таким образом, вы также можете встроить значение временной метки по УМОЛЧАНИЮ в определение столбца соответствующего объекта как so или подобное:

 @Column(name="datecreated", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
  

Это гарантирует, что при создании таблицы определение будет применено с использованием свойства auto DDL настроек hibernate.

Надеюсь, это прояснит

Ответ №2:

В вашем классе модели изображения используйте временную метку

 @CreationTimestamp
@Column
private Timestamp timestamp;