【问题标题】:How to set a default entity property value with Hibernate如何使用 Hibernate 设置默认实体属性值
【发布时间】:2011-03-07 19:39:24
【问题描述】:

如何在 Hibernate 字段中设置默认值?

【问题讨论】:

  • 您使用的是 XML 配置文件还是注解?
  • 下面的答案只给出了 JPA 解决方案,这是正确的,但是对于 Hibernate 解决方案,请参阅 stackoverflow.com/questions/28107554/… 你必须使用 @ColumnDefault

标签: java hibernate orm entity default-value


【解决方案1】:

为字段设置一个默认值怎么样?

private String _foo = "default";

//property here
public String Foo

如果他们传递了一个值,那么它将被覆盖,否则,你有一个默认值。

【讨论】:

  • @michali:默认值的作用不会阻止更新值,是吗?
【解决方案2】:

如果你想要一个真正的数据库默认值,使用columnDefinition:

@Column(name = "myColumn", nullable = false, columnDefinition = "int default 100") 

请注意columnDefinition 中的字符串取决于数据库。此外,如果您选择此选项,则必须使用dynamic-insert,因此Hibernate 不包括插入时具有null 值的列。否则谈论默认是无关紧要的。

但是,如果您不想要数据库默认值,而只是 Java 代码中的默认值,只需像这样初始化您的变量 - private Integer myColumn = 100;

【讨论】:

  • 带注释:@org.hibernate.annotations.Entity(dynamicInsert = true)
  • 目前org.hibernate.annotations.Entity 已被弃用。应该改用@DynamicInsert 注解。
  • 我不建议在这种情况下使用 columnDefinition,这不能从数据库移植到另一个数据库,并且您需要了解服务器的特定 SQL 语言。
  • @DynamicInsert 需要添加到数据库 pojo 类中。
  • 我建议使用@ColumnDefault 而不是 columnDefinition,因为它更独立于数据库docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/…
【解决方案3】:

一种解决方案是让您的 getter 检查您正在使用的任何值是否为 null(或任何未初始化状态),如果等于该值,则返回您的默认值:

public String getStringValue(){
     return (this.stringValue == null) ? "Default" : stringValue;
}

【讨论】:

  • 我正在使用一个映射器,它在我的实体对象上调用 setter。在 getter 和 setter 上使用您的代码 sn-p 是否有缺点?
  • 我正在使用 spring boot 。在我尝试过的那个实体类中:> private Long trianglesCount; @Column(name = "triangles_count") public Long getTrianglesCount() { if(this.trianglesCount == null) return 0L;否则返回 this.trianglesCount;默认情况下,这不会保存 0L。它在数据库中保存 null。
【解决方案4】:

如果你想在数据库中做:

在数据库中设置默认值(sql server 示例):

ALTER TABLE [TABLE_NAME] ADD  CONSTRAINT [CONSTRAINT_NAME]  DEFAULT (newid()) FOR [COLUMN_NAME]

映射休眠文件:

    <hibernate-mapping ....
    ...    
    <property name="fieldName" column="columnName" type="Guid" access="field" not-null="false"  insert="false" update="false"  />
    ...

看,关键是insert="false" update="false"

【讨论】:

  • Oracle有一个问题:如果属性不为null,它的值仍然是默认值。不是实际值。
【解决方案5】:

您可以使用@PrePersist注解并在pre-persist阶段设置默认值。

类似的东西:

//... some code
private String myProperty;
//... some code

@PrePersist
public void prePersist() {
    if(myProperty == null) //We set default value in case if the value is not set yet.
        myProperty = "Default value";
}

// property methods
@Column(nullable = false) //restricting Null value on database level.
public String getMyProperty() {
    return myProperty;
}

public void setMyProperty(String myProperty) {
    this.myProperty= myProperty;
}

此方法不依赖于 Hibernate 下的数据库类型/版本。在持久化映射对象之前设置默认值。

【讨论】:

  • 鉴于您的示例未使用setMyProperty。为什么要包含它?
  • 我只是给出标准 java 属性的休眠注解示例(具有公共 get/set 方法的私有变量)。我注意到并纠正了一个错误...... set 方法参数的字符串类型丢失。
【解决方案6】:
<property name="age" type="integer">
<column name="age" not-null="false" default="null" />
</property>

【讨论】:

【解决方案7】:

我搜索了这个并找到了许多关于列默认值的答案。如果你想使用 SQL 表中定义的默认值,那么在@Column Annotation 中使用 "insertable = false"。可插入

@Column(name = columnName, length = lengthOfColumn, insertable = false)

如果您使用的是 columnDefination,则 @Column 注释可能不起作用,因为它依赖于数据库。

【讨论】:

  • 这非常适用于像“createdAt”这样的列,您总是希望使用数据库默认值。谢谢!
【解决方案8】:

与 Oracle 合作,我试图为 Enum 插入默认值

我发现以下方法效果最好。

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private EnumType myProperty = EnumType.DEFAULT_VALUE;

【讨论】:

    【解决方案9】:

    您可以使用 java 类构造函数来设置默认值。例如:

    public class Entity implements Serializable{
     private Double field1
     private Integer field2;
     private T fieldN;
    
     public Entity(){
      this.field1=0.0;
      this.field2=0;
      ...
      this.fieldN= <your default value>
     }
    
     //Setters and Getters
    ...
    
    }
    

    【讨论】:

      【解决方案10】:

      使用@ColumnDefault()注解。这只是休眠。

      【讨论】:

        【解决方案11】:

        使用休眠注解。

        @ColumnDefault("-1")
        private Long clientId;
        

        如果表已存在,则重新创建表以使更改生效。

        【讨论】:

        • 谢谢,它有效。但我不得不重新创建表格。
        • 这应该是真正的解决方案,使用当前答案提出的 columnDefinition 很麻烦,您必须包含类型。在我看来,@ColumnDefault 注释要容易得多。
        【解决方案12】:

        如果要在数据库方面设置默认值,只需设置@Column( columnDefinition = "int default 1")

        但是,如果您打算在您的 java 应用程序中设置一个默认值,您可以在您的类属性上设置它,如下所示:private Integer attribute = 1;

        【讨论】:

          【解决方案13】:

          我正在使用 hibernate 5 和 postgres,这对我有用。

          @Column(name = "ACCOUNT_TYPE", ***nullable***=false, columnDefinition="varchar2 default 'END_USER'")
          @Enumerated(EnumType.STRING)
          private AccountType accountType;
          

          【讨论】:

            【解决方案14】:

            使用表中任何列的默认值。那么您必须将@DynamicInsert 定义为true,否则您只需定义@DynamicInsert。因为 hibernate 默认情况下将其作为 true。 考虑作为给定的例子:

            @AllArgsConstructor
            @Table(name = "core_contact")
            @DynamicInsert
            public class Contact implements Serializable {
            
                @Column(name = "status", columnDefinition = "int default 100")
                private Long status;
            
            }
            

            【讨论】:

              【解决方案15】:

              默认实体属性值

              如果要设置默认的实体属性值,则可以使用默认值初始化实体字段。

              例如,您可以将默认的createdOn 实体属性设置为当前时间,如下所示:

              @Column(
                  name = "created_on"
              )
              private LocalDateTime createdOn = LocalDateTime.now();
              

              使用 JPA 的默认列值

              如果您使用 JPA 和 Hibernate 生成 DDL 模式,虽然不建议这样做,但您可以使用 JPA @Column 注释的 columnDefinition 属性,如下所示:

              @Column(
                  name = "created_on", 
                  columnDefinition = "DATETIME(6) DEFAULT CURRENT_TIMESTAMP"
              )
              @Generated(GenerationTime.INSERT)
              private LocalDateTime createdOn;
              

              @Generated 注解是必需的,因为我们要指示 Hibernate 在刷新 Persistence Context 后重新加载实体,否则数据库生成的值将不会与内存中的实体状态同步。

              您最好使用 Flyway 之类的工具并使用 DDL 增量迁移脚本,而不是使用 columnDefinition。这样,您将在脚本中设置DEFAULT SQL 子句,而不是在 JPA 注释中。

              使用 Hibernate 的默认列值

              如果你在 Hibernate 中使用 JPA,那么你也可以使用 @ColumnDefault 注解,像这样:

              @Column(name = "created_on")
              @ColumnDefault(value="CURRENT_TIMESTAMP")
              @Generated(GenerationTime.INSERT)
              private LocalDateTime createdOn;
              

              使用 Hibernate 的默认日期/时间列值

              如果你在 Hibernate 中使用 JPA 并且想要设置创建时间戳,那么你可以使用 @CreationTimestamp 注解,像这样:

              @Column(name = "created_on")
              @CreationTimestamp
              private LocalDateTime createdOn;
              

              【讨论】:

              • 完美,使用@Generated 为我工作。但是@GeneratedValue 有什么区别?
              • @GeneratedValue 只能用于实体标识符。
              • @GeneratedValue 仅适用于实体的主键,@Generated 适用于原始值。但是对于具有@OneToOne 之类的注释的子实体或外键,我应该使用什么?因为在这种情况下,这两个注释都不适合我。
              • 使用@MapsId,如this article中所述。
              • 最后我在实体中使用@DynamicInsert解决了它,以便DBMS值在前面
              【解决方案16】:

              假设我们有一个包含子实体的实体。

              在实体上使用insertable = false, updatable = false 可防止实体创建新的子实体并位于默认 DBMS 值之前。但是这样做的问题是我们必须始终使用默认值,或者如果我们需要实体包含另一个不是默认值的子实体,我们必须尝试在运行时将这些注释更改为insertable = true, updatable = true,所以它似乎不是一条好路。

              如果在所有列中使用insertable = false, updatable = false 更有意义,则在子实体内部,这样无论我们使用哪种方法都不会创建更多子实体(@DynamicInsert 没有必要)

              可以通过多种方式插入默认值,例如默认实体属性值使用构造函数或设置器。其他方法(例如将 JPA 与 columnDefinition 一起使用)的缺点是它们默认插入 null,并且 DBMS 的默认值不在前面。


              使用 DBMS 插入默认值,可选使用 Hibernate

              但是使用@DynamicInsert,当我们想要插入具有默认值的子实体时,我们避免向数据库发送空值,而反过来我们允许插入具有非默认值的子实体。

              对于插入,该实体是否应该使用动态 sql 生成,在准备好的 sql 语句中只引用非空列?

              鉴于以下需求:

              • 实体不负责创建新的子实体。
              • 插入实体时,子实体是在 DBMS 中定义为默认值的实体。
              • 可以使用具有非默认 UUID 的子实体创建实体。

              DBMS:PostgreSQL | 语言:科特林

              @Entity
              @Table(name = "entity")
              @DynamicInsert
              data class EntityTest(
                      @Id @GeneratedValue @Column(name = "entity_uuid") val entityUUID: UUID? = null,
              
                      @OneToOne(cascade = [CascadeType.ALL])
                      @JoinColumn(name = "subentity_uuid", referencedColumnName = "subentity_uuid")
                      var subentityTest: SubentityTest? = null
              ) {}
              
              @Entity
              @Table(name = "subentity")
              data class SubentityTest(
                      @Id @GeneratedValue @Column(name = "subentity_uuid", insertable = false, updatable = false) var subentityUUID: UUID? = null,
                      @Column(insertable = false, updatable = false) var name: String,
              ) {
                      constructor() : this(name = "")
              }
              

              并且该值是在数据库中默认设置的:

              alter table entity alter column subentity_uuid set default 'd87ee95b-06f1-52ab-83ed-5d882ae400e6'::uuid;
              

              GL

              【讨论】:

                【解决方案17】:

                我们可以有注释@Column的getter

                所有@column 都应该在getter 中单独注释,而不是直接变量声明。这样我们就可以解决了。

                    @Column(name = "string_value")
                public String getStringValue(){
                         return (this.stringValue == null) ? "Default" : stringValue;
                    }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2020-08-12
                  • 1970-01-01
                  • 2012-11-15
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-03-08
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多