É possível definir um valor padrão para colunas na JPA e se, como isso é feito usando anotações?
java
jpa
annotations
homaxto
fonte
fonte
Respostas:
Na verdade, é possível na JPA, embora um pouco de hack usando a
columnDefinition
propriedade da@Column
anotação, por exemplo:fonte
insertable=false
se a coluna fosse anulável (e para evitar o argumento desnecessário da coluna).Você pode fazer o seguinte:
Lá! Você acabou de usar zero como valor padrão.
Observe que isso será útil se você estiver acessando apenas o banco de dados a partir deste aplicativo. Se outros aplicativos também usarem o banco de dados, faça essa verificação no banco de dados usando o atributo de anotação columnDefinition de Cameron , ou de alguma outra maneira.
fonte
Example
objeto como um protótipo para a pesquisa. Depois de definir um valor padrão, uma consulta de exemplo do Hibernate não ignorará mais a coluna associada, onde anteriormente a ignoraria porque era nula. Uma abordagem melhor é definir todos os valores padrão antes de chamar um Hibernatesave()
ouupdate()
. Isso imita melhor o comportamento do banco de dados, que define valores padrão quando ele salva uma linha.null
por exemplo). Usando@PrePersist
e@PreUpdate
é uma opção melhor imho.columnDefinition
A propriedade não é independente do banco de dados e@PrePersist
substitui sua configuração antes da inserção; "valor padrão" é outra coisa; o valor padrão é usado quando o valor não é definido explicitamente.outra abordagem é usar javax.persistence.PrePersist
fonte
if (createdt != null) createdt = new Date();
ou algo assim? No momento, isso substituirá um valor especificado explicitamente, o que parece torná-lo realmente não padrão.if (createdt == null) createdt = new Date();
null
verificação.Em 2017, o JPA 2.1 ainda possui apenas
@Column(columnDefinition='...')
para o qual você coloca a definição SQL literal da coluna. O que é bastante flexível e obriga a declarar também outros aspectos, como tipo, causando um curto-circuito na visão da implementação da JPA sobre esse assunto.Hibernate, porém, tem o seguinte:
Duas notas para isso:
1) Não tenha medo de ficar fora do padrão. Trabalhando como desenvolvedor do JBoss, já vi alguns processos de especificação. A especificação é basicamente a linha de base que os grandes players em determinado campo estão dispostos a comprometer-se a apoiar na próxima década. É verdade para segurança, para mensagens, ORM não faz diferença (embora o JPA cubra bastante). Minha experiência como desenvolvedor é que, em um aplicativo complexo, mais cedo ou mais tarde você precisará de uma API não padrão. E
@ColumnDefault
é um exemplo quando supera os negativos do uso de uma solução não padrão.2) É bom como todo mundo acena a inicialização do @PrePersist ou membro do construtor. Mas isso não é o mesmo. E as atualizações SQL em massa? E as instruções que não definem a coluna?
DEFAULT
tem sua função e isso não é substituível ao inicializar um membro da classe Java.fonte
O JPA não suporta isso e seria útil se o fizesse. O uso de columnDefinition é específico do banco de dados e não é aceitável em muitos casos. definir um padrão na classe não é suficiente quando você recupera um registro com valores nulos (o que normalmente acontece quando você executa novamente os testes antigos do DBUnit). O que eu faço é isso:
O boxe automático em Java ajuda muito nisso.
fonte
Vendo como eu me deparei com isso no Google enquanto tentava resolver o mesmo problema, vou apenas apresentar a solução que preparei para o caso de alguém achar útil.
Do meu ponto de vista, existem apenas 1 soluções para esse problema - @PrePersist. Se você fizer isso no @PrePersist, precisará verificar se o valor já foi definido.
fonte
@PrePersist
caso de uso do OP.@Column(columnDefinition=...)
não parece muito elegante.Acabei de testar o problema. Funciona muito bem. Obrigado pela dica.
Sobre os comentários:
Este não define o valor padrão da coluna no banco de dados (é claro).
fonte
você pode usar o java reflect api:
Isso é comum:
fonte
Field[] fields = object.getClass().getDeclaredFields();
no tambémfor()
pode ser bom. E também adicionefinal
ao seu parâmetro / exceções capturadas, pois você não desejaobject
ser modificado por acidente. Além disso, adicione um controlo sobrenull
:if (null == object) { throw new NullPointerException("Parameter 'object' is null"); }
. Isso garante queobject.getClass()
é seguro invocar e não dispara aNPE
. O motivo é evitar erros de programadores preguiçosos. ;-)Eu uso
columnDefinition
e funciona muito bemfonte
Você não pode fazer isso com a anotação da coluna. Eu acho que a única maneira é definir o valor padrão quando um objeto é criado. Talvez o construtor padrão seja o lugar certo para fazer isso.
fonte
@Column
próximos. E também sinto falta de comentários sendo definidos (tirados do Java doctag).No meu caso, modifiquei o código-fonte do núcleo de hibernação, bem, para introduzir uma nova anotação
@DefaultValue
:Bem, esta é uma solução apenas para hibernação.
fonte
@Column(columnDefinition='...')
não funciona quando você define a restrição padrão no banco de dados enquanto insere os dados.insertable = false
e removercolumnDefinition='...'
da anotação, para que o banco de dados insira automaticamente o valor padrão do banco de dados.insertable = false
Hibernate / JPA, ele funcionará.fonte
No meu caso, devido ao campo ser LocalDateTime, usei isso, é recomendado devido à independência do fornecedor
fonte
As anotações JPA e Hibernate não suportam a noção de um valor padrão da coluna. Como solução alternativa para essa limitação, defina todos os valores padrão imediatamente antes de chamar um Hibernate
save()
ouupdate()
na sessão. O mais próximo possível (menos que o Hibernate defina os valores padrão) imita o comportamento do banco de dados, que define valores padrão quando ele salva uma linha em uma tabela.Ao contrário de definir os valores padrão na classe de modelo, como sugere esta resposta alternativa , essa abordagem também garante que as consultas de critérios que usam um
Example
objeto como um protótipo para a pesquisa continuem funcionando como antes. Quando você define o valor padrão de um atributo anulável (um que tenha um tipo não primitivo) em uma classe de modelo, uma consulta por exemplo do Hibernate não ignorará mais a coluna associada, onde anteriormente o ignoraria porque era nulo.fonte
Isso não é possível no JPA.
Aqui está o que você pode fazer com a anotação de coluna: http://java.sun.com/javaee/5/docs/api/javax/persistence/Column.html
fonte
Se você estiver usando um duplo, poderá usar o seguinte:
Sim, é db específico.
fonte
Você pode definir o valor padrão no designer de banco de dados ou quando criar a tabela. Por exemplo, no SQL Server, você pode definir o cofre padrão de um campo Data para (
getDate()
). Useinsertable=false
conforme mencionado na sua definição de coluna. A JPA não especificará essa coluna nas inserções e o banco de dados gerará o valor para você.fonte
Você precisa de
insertable=false
você@Column
anotá- . A JPA ignorará a coluna ao inserir no banco de dados e o valor padrão será usado.Consulte este link: http://mariemjabloun.blogspot.com/2014/03/resolved-set-database-default-value-in.html
fonte
nullable=false
falhará com umSqlException
:Caused by: java.sql.SQLException: Column 'opening_times_created' cannot be null
. Aqui eu esqueci de definir o timestamp "criado" comopeningTime.setOpeningCreated(new Date())
. É uma boa maneira de ter consistência, mas é isso que o questionador não estava perguntando.