Java Hibernate模型类配置不';使用“创建表查询”时不能反映;hibernate.hbm2ddl.auto=update";

Java Hibernate模型类配置不';使用“创建表查询”时不能反映;hibernate.hbm2ddl.auto=update";,java,mysql,hibernate,Java,Mysql,Hibernate,我正在从事Spring(4.x)-Hibernate(5.2.x)web应用程序项目 模型类 @Entity @Table( name = "users" ) public class User { @Id @Column( name="ID" ) @GeneratedValue( strategy = GenerationType.IDENTITY ) private Long id; @Temporal( TemporalType.TIMESTAM

我正在从事Spring(4.x)-Hibernate(5.2.x)web应用程序项目

模型类

@Entity
@Table( name = "users" )
public class User {

    @Id
    @Column( name="ID" )
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Long id;

    @Temporal( TemporalType.TIMESTAMP )
    @Column( name="CREATED_AT", insertable=false, nullable=false )
    @Generated( GenerationTime.INSERT )
    private Date createdAt;

    @Temporal( TemporalType.TIMESTAMP )
    @Column( name="UPDATED_AT", insertable=false, updatable=false, nullable=false )
    @Generated( GenerationTime.ALWAYS )
    private Date updatedAt;

    public enum Role {
        ADMIN,
        USER,
        GUEST
    }
    @NotNull
    @Column( name="ROLE" )
    @Enumerated( EnumType.STRING )
    private Role role;

    //getters & setters
}
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
休眠属性

@Entity
@Table( name = "users" )
public class User {

    @Id
    @Column( name="ID" )
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Long id;

    @Temporal( TemporalType.TIMESTAMP )
    @Column( name="CREATED_AT", insertable=false, nullable=false )
    @Generated( GenerationTime.INSERT )
    private Date createdAt;

    @Temporal( TemporalType.TIMESTAMP )
    @Column( name="UPDATED_AT", insertable=false, updatable=false, nullable=false )
    @Generated( GenerationTime.ALWAYS )
    private Date updatedAt;

    public enum Role {
        ADMIN,
        USER,
        GUEST
    }
    @NotNull
    @Column( name="ROLE" )
    @Enumerated( EnumType.STRING )
    private Role role;

    //getters & setters
}
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
自动生成的查询

create table users (
    ID bigint not null auto_increment,
    CREATED_AT datetime not null,
    UPDATED_AT datetime not null,
    ROLE varchar(255) not null,
    primary key (id)
)
我希望有一个查询

  • 在DATETIME创建\u非空默认当前\u时间戳
  • 在DATETIME更新\u在更新当前\u时间戳时不为空
  • 角色枚举('ADMIN'、'USER'、'GUEST')VARCHAR(255)不为空
这是它的工作方式还是我的配置错误?进行了一些搜索,但没有找到明确的解决方案,除了这些

  • @Column(name=“CREATED\u AT”,nullable=false,columnDefinition=“TIMESTAMP default CURRENT\u TIMESTAMP on update CURRENT\u TIMESTAMP”)
  • @ColumnDefault(“NOW()”)

但这些定义取决于底层数据库,我就是这么认为的。需要一个更像java/hibernate的配置,就像我使用的,但不工作

使用当前版本的jpa(hibernate provider)

标识通过DDL(数据定义语言)应用于关联列的默认值

所以,似乎不可能像您预期的那样,基于java生成具有默认值的列的表

CREATED_AT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAM
如果我们想切换到其他db服务器(oracle->mysql),这是非常不方便的,因为DDL语法可能不同。但是jpa将来可能有这个功能(也许)

对于您的问题,您必须使用DDL的默认值

开发人员通常使用另一种方法来确保在插入之前始终初始化列。但它不会为数据库中的列生成默认值

@PrePersist
void preInsert() {
   if (this.createdTime == null)
       this.createdTime = new Date();
}
如果其他开发人员使用sql native进行查询,则可能会失败


如果您找到了其他解决方案,请更正,希望能有所帮助

有一些方法可以解决你的问题

  • 使用@PrePersist
  • 使用@CreationTimestamp和@UpdateTimestamp
  • 将DDL与上述解决方案相结合

  • p/s:您应该使用数据库迁移工具,如Flyway、Liquibase等。。。这些工具将对您有很大帮助。

    DDL通常是特定于数据库的。要获得不同的DDL,您可能需要查看Flyway、Liquibase等

    java/hibernate中的另一种方法是:

    @Generated
    已改装为使用
    @ValueGenerationType
    元注释。使用
    @ValueGenerationType
    元注释 声明用于标记实体的自定义注释时 需要特定生成策略的属性。实际的 必须将生成逻辑添加到实现
    注释值生成
    界面

    如果需要在内存中生成时间戳值,则必须使用以下映射:

    实体:

    @Entity(name = "Event")
    public static class Event {
    
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "`timestamp`")
    @FunctionCreationTimestamp
    private Date timestamp;
    
    //Constructors, getters, and setters are omitted for brevity
    }
    
    时间戳生成类:

    @ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FunctionCreationTimestamp {}
    
    public static class FunctionCreationValueGeneration
        implements AnnotationValueGeneration<FunctionCreationTimestamp> {
    
    @Override
    public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
    }
    
    /**
     * Generate value on INSERT
     * @return when to generate the value
     */
    public GenerationTiming getGenerationTiming() {
        return GenerationTiming.INSERT;
    }
    
    /**
     * Returns the in-memory generated value
     * @return {@code true}
     */
    public ValueGenerator<?> getValueGenerator() {
        return (session, owner) -> new Date( );
    }
    
    /**
     * Returns false because the value is generated by the database.
     * @return false
     */
    public boolean referenceColumnInSql() {
        return false;
    }
    
    /**
     * Returns null because the value is generated in-memory.
     * @return null
     */
    public String getDatabaseGeneratedReferencedColumnValue() {
        return null;
    }
    }
    
    如您所见,
    newdate()
    对象值用于分配时间戳列值

    参考:


    PS:(只是一个想法)您甚至可以使用if-else子句实现特定于数据库的实现。

    使用
    @CreationTimestamp
    @UpdateTimestamp
    。这仍然不起作用。谢谢@LiemLe A
    @PrePersist
    @CreationTimestamp
    不会创建具有默认值的表。POJO中的DDL依赖于数据库。正如@huy所指出的,目前的JPA/Hibernate似乎不可能完全实现我想要的。不管怎样,我还是决定使用
    @ColumnDefinition
    。谢谢@huy,正如您所指出的,使用当前的JPA/Hibernate似乎不可能完全实现我想要的。还是决定使用
    @ColumnDefinition
    。将在这里更新,如果我发现了更好的解决方案,可能会在下一个版本中