【问题标题】:In SpringBoot, what is the correct way in annotating fields with default value在SpringBoot中,用默认值注释字段的正确方法是什么
【发布时间】:2020-04-25 17:19:15
【问题描述】:

我是 Spring Boot 的新手。我正在尝试使用带有 Mysql Workbench 的 Spring Tool Suite 创建一个应用程序,该应用程序使用 JPA、MysqlConnectorJ 作为依赖项。

我有一个名为“CredentialType”的实体

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "mactyp")
public class CredentialType {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="credential_type_id")
    private Long id;
    @Column(name="credential_type_name")
    private String name;
    @Column(name="date_added")
    private LocalDateTime dateAdded;
    @Column(name="date_modified")
    private Date dateLastModified;
    @Column(name="is_active")
    private boolean isActive;

    ...getters() and setters()...
}

下面的表定义(Mysql Workbench 生成的脚本)

CREATE TABLE `mactyp` (
  `credential_type_id` int(11) NOT NULL AUTO_INCREMENT,
  `credential_type_name` varchar(45) NOT NULL,
  `date_added` datetime NOT NULL DEFAULT current_timestamp(),
  `date_modified` datetime DEFAULT NULL,
  `is_active` bit(1) NOT NULL DEFAULT b'1',
  PRIMARY KEY (`credential_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

date_added 列默认值为current_timestamp

但是,当我尝试运行下面的测试时,

@Test
public void testCreateCredentialType() {
    //DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    //LocalDateTime now = LocalDateTime.now();
    //System.out.println(dtf.format(now));

    CredentialType credentialType = new CredentialType();
    credentialType.setName("Application");
    //credentialType.setDateAdded(now);

    credentialTypeRepository.save(credentialType);
}

返回

2020-04-26 01:09:23.962  WARN 8352 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1048, SQLState: 23000
2020-04-26 01:09:23.962 ERROR 8352 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'date_added' cannot be null

我期待它会自动在 Mysql 中插入日期时间/时间戳。我不知道为什么会出现错误。

谢谢。

【问题讨论】:

    标签: mysql spring-boot spring-data-jpa mysql-workbench spring-boot-test


    【解决方案1】:

    添加 insertable = false 将删除 hibernate 生成的插入脚本中添加的列(但可用于 select),并使用数据库默认值。

     @Column(name="date_added", insertable = false)
     private LocalDateTime dateAdded;
    

    【讨论】:

      【解决方案2】:
      `date_added` datetime NOT NULL DEFAULT current_timestamp()
      

      DEFAULT 不防范null。在普通 SQL 中,如果设置date_added = null,则该列将为空,因此将引发错误。

      默认值仅适用于您执行insert into mactype(credential_type_id, credential_type_name) values (.., ..) 之类的操作并且未指定您已为其指定默认值的列的情况。

      在您的情况下,您可以在实体类中利用 @PrePersist@PreUpdate 注释方法。

      【讨论】:

        【解决方案3】:

        当数据插入数据库时​​date_added值为null。 表示插入查询执行如下

        insert into mactyp(.., date_added,...) values (..,null, ..)
        

        因此,通过此查询,您尝试在非空字段上设置空值。 这就是错误提示的原因

        Column 'date_added' cannot be null
        

        当您不尝试使用查询插入列时,将应用 mysql 默认值。

        在列上使用@CreationTimestamp 来设置查询中的当前时间戳。

        @CreationTimestamp
        private LocalDateTime dateAdded;
        

        了解更多详情here

        【讨论】:

          【解决方案4】:

          对于Date 字段,您可以使用以下注释:

          @Temporal(TemporalType.TIMESTAMP)
          @CreationTimestamp
          @Column(name = "created_at", nullable = false)
          private Date createdAt;
          
          @Temporal(TemporalType.TIMESTAMP)
          @UpdateTimestamp
          @Column(name = "updated_at", nullable = true)
          private Date updatedAt;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-09-09
            • 2012-11-30
            • 2011-01-22
            • 2018-10-26
            • 1970-01-01
            • 2015-03-05
            • 1970-01-01
            • 2015-07-03
            相关资源
            最近更新 更多