Java 为 JPA 中的列设置默认值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/197045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:12:16  来源:igfitidea点击:

Setting default values for columns in JPA

javajpaannotations

提问by homaxto

Is it possible to set a default value for columns in JPA, and if, how is it done using annotations?

是否可以为 JPA 中的列设置默认值,如果使用注释是如何完成的?

采纳答案by Cameron Pope

Actually it is possible in JPA, although a little bit of a hack using the columnDefinitionproperty of the @Columnannotation, for example:

实际上在 JPA 中是可能的,尽管使用注释的columnDefinition属性有点小技巧@Column,例如:

@Column(name="Price", columnDefinition="Decimal(10,2) default '100.00'")

回答by PEELY

This isn't possible in JPA.

这在 JPA 中是不可能的。

Here's what you cando with the Column annotation: http://java.sun.com/javaee/5/docs/api/javax/persistence/Column.html

以下是您可以使用 Column 注释执行的操作:http: //java.sun.com/javaee/5/docs/api/javax/persistence/Column.html

回答by Timo

You can't do this with the column annotation. I think the only way is to set the default value when a object is created. Maybe the default constructor would be the right place to do that.

您不能使用列注释执行此操作。我认为唯一的方法是在创建对象时设置默认值。也许默认构造函数将是执行此操作的正确位置。

回答by Pablo Venturino

You can do the following:

您可以执行以下操作:

@Column(name="price")
private double price = 0.0;

There! You've just used zero as the default value.

那里!您刚刚使用了零作为默认值。

Note this will serve you if you're only accessing the database from this application. If other applications also use the database, then you should make this check from the database using Cameron'scolumnDefinitionannotation attribute, or some other way.

请注意,如果您仅从该应用程序访问数据库,这将为您服务。如果其他应用程序也使用该数据库,那么您应该使用Cameron 的columnDefinition注释属性或其他方式从数据库进行此检查。

回答by asd

@Column(columnDefinition="tinyint(1) default 1")

I just tested the issue. It works just fine.Thanks for the hint.

我刚刚测试了这个问题。它工作得很好。谢谢你的提示。



About the comments:

关于评论:

@Column(name="price") 
private double price = 0.0;

This one doesn'tset the default column value in the database (of course).

这个没有设置数据库中的默认列值(当然)。

回答by Marco

JPA doesn't support that and it would be useful if it did. Using columnDefinition is DB-specific and not acceptable in many cases. setting a default in the class is not enough when you retrieve a record having null values (which typically happens when you re-run old DBUnit tests). What I do is this:

JPA 不支持,如果支持它会很有用。使用 columnDefinition 是特定于数据库的,在许多情况下是不可接受的。当您检索具有空值的记录(这通常发生在您重新运行旧的 DBUnit 测试时)时,在类中设置默认值是不够的。我做的是这样的:

public class MyObject
{
    int attrib = 0;

    /** Default is 0 */
    @Column ( nullable = true )
    public int getAttrib()

    /** Falls to default = 0 when null */
    public void setAttrib ( Integer attrib ) {
       this.attrib = attrib == null ? 0 : attrib;
    }
}

Java auto-boxing helps a lot in that.

Java 自动装箱在这方面有很大帮助。

回答by Derek Mahar

Neither JPA nor Hibernate annotations support the notion of a default column value. As a workaround to this limitation, set all default values just before you invoke a Hibernate save()or update()on the session. This closely as possible (short of Hibernate setting the default values) mimics the behaviour of the database which sets default values when it saves a row in a table.

JPA 和 Hibernate 注释都不支持默认列值的概念。作为此限制的解决方法,请在调用 Hibernate 之前save()update()在会话中设置所有默认值。这尽可能接近(缺少 Hibernate 设置默认值)模仿数据库的行为,该行为在将行保存在表中时设置默认值。

Unlike setting the default values in the model class as this alternative answersuggests, this approach also ensures that criteria queries that use an Exampleobject as a prototype for the search will continue to work as before. When you set the default value of a nullable attribute (one that has a non-primitive type) in a model class, a Hibernate query-by-example will no longer ignore the associated column where previously it would ignore it because it was null.

与此替代答案建议的在模型类中设置默认值不同,此方法还确保使用Example对象作为搜索原型的条件查询将继续像以前一样工作。当您在模型类中设置可空属性(具有非原始类型的属性)的默认值时,Hibernate 示例查询将不再忽略关联列,而之前它会忽略它,因为它为空。

回答by TC1

Seeing as I stumbled upon this from Google while trying to solve the very same problem, I'm just gonna throw in the solution I cooked up in case someone finds it useful.

看到我在尝试解决同样的问题时从谷歌偶然发现了这个,我只是要抛出我准备的解决方案,以防有人发现它有用。

From my point of view there's really only 1 solutions to this problem -- @PrePersist. If you do it in @PrePersist, you gotta check if the value's been set already though.

在我看来,这个问题实际上只有 1 个解决方案——@PrePersist。如果您在@PrePersist 中执行此操作,则必须检查该值是否已设置。

回答by Xiè Jìléi

In my case, I modified hibernate-core source code, well, to introduce a new annotation @DefaultValue:

就我而言,我修改了 hibernate-core 源代码,以引入新的注释@DefaultValue

commit 34199cba96b6b1dc42d0d19c066bd4d119b553d5
Author: Lenik <xjl at 99jsj.com>
Date:   Wed Dec 21 13:28:33 2011 +0800

    Add default-value ddl support with annotation @DefaultValue.

diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/DefaultValue.java b/hibernate-core/src/main/java/org/hibernate/annotations/DefaultValue.java
new file mode 100644
index 0000000..b3e605e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/DefaultValue.java
@@ -0,0 +1,35 @@
+package org.hibernate.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Specify a default value for the column.
+ *
+ * This is used to generate the auto DDL.
+ *
+ * WARNING: This is not part of JPA 2.0 specification.
+ *
+ * @author 谢继雷
+ */
[email protected]({ FIELD, METHOD })
+@Retention(RUNTIME)
+public @interface DefaultValue {
+
+    /**
+     * The default value sql fragment.
+     *
+     * For string values, you need to quote the value like 'foo'.
+     *
+     * Because different database implementation may use different 
+     * quoting format, so this is not portable. But for simple values
+     * like number and strings, this is generally enough for use.
+     */
+    String value();
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java
index b289b1e..ac57f1a 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java
@@ -29,6 +29,7 @@ import org.hibernate.AnnotationException;
 import org.hibernate.AssertionFailure;
 import org.hibernate.annotations.ColumnTransformer;
 import org.hibernate.annotations.ColumnTransformers;
+import org.hibernate.annotations.DefaultValue;
 import org.hibernate.annotations.common.reflection.XProperty;
 import org.hibernate.cfg.annotations.Nullability;
 import org.hibernate.mapping.Column;
@@ -65,6 +66,7 @@ public class Ejb3Column {
    private String propertyName;
    private boolean unique;
    private boolean nullable = true;
+   private String defaultValue;
    private String formulaString;
    private Formula formula;
    private Table table;
@@ -175,7 +177,15 @@ public class Ejb3Column {
        return mappingColumn.isNullable();
    }

-   public Ejb3Column() {
+   public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    public Ejb3Column() {
    }

    public void bind() {
@@ -186,7 +196,7 @@ public class Ejb3Column {
        }
        else {
            initMappingColumn(
-                   logicalColumnName, propertyName, length, precision, scale, nullable, sqlType, unique, true
+                   logicalColumnName, propertyName, length, precision, scale, nullable, sqlType, unique, defaultValue, true
            );
            log.debug( "Binding column: " + toString());
        }
@@ -201,6 +211,7 @@ public class Ejb3Column {
            boolean nullable,
            String sqlType,
            boolean unique,
+           String defaultValue,
            boolean applyNamingStrategy) {
        if ( StringHelper.isNotEmpty( formulaString ) ) {
            this.formula = new Formula();
@@ -217,6 +228,7 @@ public class Ejb3Column {
            this.mappingColumn.setNullable( nullable );
            this.mappingColumn.setSqlType( sqlType );
            this.mappingColumn.setUnique( unique );
+           this.mappingColumn.setDefaultValue(defaultValue);

            if(writeExpression != null && !writeExpression.matches("[^?]*\?[^?]*")) {
                throw new AnnotationException(
@@ -454,6 +466,11 @@ public class Ejb3Column {
                    else {
                        column.setLogicalColumnName( columnName );
                    }
+                   DefaultValue _defaultValue = inferredData.getProperty().getAnnotation(DefaultValue.class);
+                   if (_defaultValue != null) {
+                       String defaultValue = _defaultValue.value();
+                       column.setDefaultValue(defaultValue);
+                   }

                    column.setPropertyName(
                            BinderHelper.getRelativePath( propertyHolder, inferredData.getPropertyName() )
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
index e57636a..3d871f7 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
@@ -423,6 +424,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
                getMappingColumn() != null ? getMappingColumn().isNullable() : false,
                referencedColumn.getSqlType(),
                getMappingColumn() != null ? getMappingColumn().isUnique() : false,
+               null, // default-value
                false
        );
        linkWithValue( value );
@@ -502,6 +504,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
                getMappingColumn().isNullable(),
                column.getSqlType(),
                getMappingColumn().isUnique(),
+               null, // default-value
                false //We do copy no strategy here
        );
        linkWithValue( value );

Well, this is a hibernate-only solution.

嗯,这是一个仅限休眠的解决方案。

回答by Tong

I use columnDefinitionand it works very good

我使用columnDefinition并且效果很好

@Column(columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

private Date createdDate;