Установка значений по умолчанию для столбцов в JPA - PullRequest
221 голосов
/ 13 октября 2008

Можно ли установить значение по умолчанию для столбцов в JPA, и если, как это делается с использованием аннотаций?

Ответы [ 18 ]

283 голосов
/ 18 июня 2009

Вы можете сделать следующее:

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

Там! Вы только что использовали ноль в качестве значения по умолчанию.

Обратите внимание, это будет вам полезно, если вы обращаетесь к базе данных только из этого приложения. Если другие приложения также используют базу данных, вам следует выполнить эту проверку из базы данных, используя Cameron's columnDefinition атрибут аннотации или каким-либо другим способом.

214 голосов
/ 17 декабря 2008

На самом деле это возможно в JPA, хотя немного взломать, используя свойство columnDefinition аннотации @Column, например:

@Column(name="Price", columnDefinition="Decimal(10,2) default '100.00'")
100 голосов
/ 17 ноября 2012

другой подход использует javax.persistence.PrePersist

@PrePersist
void preInsert() {
   if (this.createdTime == null)
       this.createdTime = new Date();
}
36 голосов
/ 10 февраля 2017

В 2017 году JPA по-прежнему имеет только @Column(columnDefinition='...'), в который вы помещаете буквальное определение SQL столбца. Что довольно негибко и заставляет вас также объявлять другие аспекты, такие как тип, коротко замыкая взгляд реализации JPA по этому вопросу.

Hibernate, хотя, имеет это:

@Column(length = 4096, nullable = false)
@org.hibernate.annotations.ColumnDefault("")
private String description;

Указывает значение ПО УМОЛЧАНИЮ для применения к связанному столбцу с помощью DDL.

Два примечания к этому:

1) Не бойтесь нестандартного поведения. Работая в качестве разработчика JBoss, я видел довольно много процессов спецификации. Спецификация - это в основном базовая линия, которую крупные игроки в данной области готовы взять на себя обязательство поддержать в течение следующего десятилетия или около того. Это верно для безопасности, для обмена сообщениями, ORM не имеет значения (хотя JPA охватывает довольно много). Мой опыт разработчика заключается в том, что в сложных приложениях рано или поздно вам все равно понадобится нестандартный API. И @ColumnDefault является примером, когда он перевешивает недостатки использования нестандартного решения.

2) Приятно, как все машут инициализацией @PrePersist или членами конструктора. Но это не то же самое. Как насчет массовых обновлений SQL? Как насчет утверждений, которые не устанавливают столбец? DEFAULT имеет свою роль и не может быть заменена инициализацией члена класса Java.

13 голосов
/ 12 апреля 2010

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-бокс помогает в этом.

9 голосов
/ 12 ноября 2010

Видя, как я наткнулся на это из Google, пытаясь решить ту же самую проблему, я просто добавлю решение, которое я приготовил, на случай, если кто-то найдет его полезным.

С моей точки зрения, на самом деле есть только 1 решение этой проблемы - @PrePersist. Если вы сделаете это в @PrePersist, вы должны проверить, установлено ли уже значение.

8 голосов
/ 31 марта 2010
@Column(columnDefinition="tinyint(1) default 1")

Я только что проверил проблему. Работает просто отлично. Спасибо за подсказку.


О комментариях:

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

Этот не устанавливает значение столбца по умолчанию в базе данных (конечно).

7 голосов
/ 05 апреля 2016

Вы можете использовать API отражения Java:

    @PrePersist
    void preInsert() {
       PrePersistUtil.pre(this);
    }

Это часто встречается:

    public class PrePersistUtil {

        private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");


        public static void pre(Object object){
            try {
                Field[] fields = object.getClass().getDeclaredFields();
                for(Field field : fields){
                    field.setAccessible(true);
                    if (field.getType().getName().equals("java.lang.Long")
                            && field.get(object) == null){
                        field.set(object,0L);
                    }else if    (field.getType().getName().equals("java.lang.String")
                            && field.get(object) == null){
                        field.set(object,"");
                    }else if (field.getType().getName().equals("java.util.Date")
                            && field.get(object) == null){
                        field.set(object,sdf.parse("1900-01-01"));
                    }else if (field.getType().getName().equals("java.lang.Double")
                            && field.get(object) == null){
                        field.set(object,0.0d);
                    }else if (field.getType().getName().equals("java.lang.Integer")
                            && field.get(object) == null){
                        field.set(object,0);
                    }else if (field.getType().getName().equals("java.lang.Float")
                            && field.get(object) == null){
                        field.set(object,0.0f);
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }
7 голосов
/ 06 января 2012

Я использую columnDefinition, и он работает очень хорошо

@Column(columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

private Date createdDate;
6 голосов
/ 07 декабря 2008

Вы не можете сделать это с аннотацией столбца. Я думаю, что единственный способ - установить значение по умолчанию при создании объекта. Может быть, конструктор по умолчанию будет правильным местом для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...