¿Es posible establecer un valor predeterminado para las columnas en JPA, y si, cómo se hace usando anotaciones?
java
jpa
annotations
homaxto
fuente
fuente
Respuestas:
En realidad, es posible en JPA, aunque un poco de pirateo utilizando la
columnDefinition
propiedad de la@Column
anotación, por ejemplo:fuente
insertable=false
si la columna es anulable (y para evitar el argumento de columna innecesario).Puedes hacer lo siguiente:
¡Ahí! Acaba de usar cero como valor predeterminado.
Tenga en cuenta que esto le servirá si solo accede a la base de datos desde esta aplicación. Si otras aplicaciones también usan la base de datos, entonces debe hacer esta verificación desde la base de datos usando el atributo de anotación columnDefinition de Cameron , o de alguna otra manera.
fuente
Example
objeto como prototipo para la búsqueda. Después de establecer un valor predeterminado, una consulta de ejemplo de Hibernate ya no ignorará la columna asociada donde anteriormente la ignoraría porque era nula. Un mejor enfoque es establecer todos los valores predeterminados justo antes de invocar un Hibernatesave()
oupdate()
. Esto imita mejor el comportamiento de la base de datos que establece los valores predeterminados cuando guarda una fila.null
por ejemplo). Usar@PrePersist
y@PreUpdate
es una mejor opción en mi humilde opinión.columnDefinition
la propiedad no es independiente de la base de datos y@PrePersist
anula su configuración antes de insertarla, el "valor predeterminado" es otra cosa, el valor predeterminado se usa cuando el valor no se establece explícitamente.otro enfoque es usar javax.persistence.PrePersist
fuente
if (createdt != null) createdt = new Date();
o algo así? En este momento, esto anulará un valor especificado explícitamente, lo que parece hacer que realmente no sea un valor predeterminado.if (createdt == null) createdt = new Date();
null
cheque.En 2017, JPA 2.1 todavía solo tiene
@Column(columnDefinition='...')
en qué poner la definición literal de SQL de la columna. Lo cual es bastante inflexible y lo obliga a declarar también los otros aspectos, como el tipo, en cortocircuito de la visión de la implementación de JPA al respecto.Sin embargo, Hibernate tiene esto:
Dos notas a eso:
1) No tengas miedo de no ser estándar. Trabajando como desarrollador de JBoss, he visto bastantes procesos de especificación. La especificación es básicamente la línea de base que los grandes jugadores en un campo determinado están dispuestos a comprometerse a apoyar durante la próxima década más o menos. Es cierto para la seguridad, para la mensajería, ORM no es la diferencia (aunque JPA cubre bastante). Mi experiencia como desarrollador es que, en una aplicación compleja, tarde o temprano necesitarás una API no estándar de todos modos. Y
@ColumnDefault
es un ejemplo cuando supera los aspectos negativos del uso de una solución no estándar.2) Es agradable cómo todos saludan a @PrePersist o a la inicialización del miembro constructor. Pero eso NO es lo mismo. ¿Qué hay de las actualizaciones masivas de SQL? ¿Qué hay de las declaraciones que no establecen la columna?
DEFAULT
tiene su rol y eso no se puede sustituir inicializando un miembro de clase Java.fuente
JPA no admite eso y sería útil si lo hiciera. El uso de columnDefinition es específico de DB y no es aceptable en muchos casos. establecer un valor predeterminado en la clase no es suficiente cuando recupera un registro que tiene valores nulos (lo que generalmente ocurre cuando vuelve a ejecutar las pruebas antiguas de DBUnit). Lo que hago es esto:
El auto-boxeo de Java ayuda mucho en eso.
fuente
Al ver que me topé con esto desde Google mientras intentaba resolver el mismo problema, solo voy a agregar la solución que preparé en caso de que alguien lo encuentre útil.
Desde mi punto de vista, solo hay 1 soluciones para este problema: @PrePersist. Si lo hace en @PrePersist, debe verificar si el valor ya se ha establecido.
fuente
@PrePersist
caso de uso de OP.@Column(columnDefinition=...)
No parece muy elegante.Acabo de probar el problema. Funciona bien Gracias por la pista.
Sobre los comentarios:
Este no establece el valor de columna predeterminado en la base de datos (por supuesto).
fuente
puedes usar el java reflect api:
Esto es común:
fuente
Field[] fields = object.getClass().getDeclaredFields();
en elfor()
. Y también agreguefinal
a su parámetro / excepciones capturadas ya que no deseaobject
ser modificado por accidente. También agregue un control sobrenull
:if (null == object) { throw new NullPointerException("Parameter 'object' is null"); }
. Eso asegura queobject.getClass()
sea seguro invocar y no desencadena aNPE
. La razón es evitar errores por parte de programadores perezosos. ;-)Yo uso
columnDefinition
y funciona muy bienfuente
No puede hacer esto con la anotación de columna. Creo que la única forma es establecer el valor predeterminado cuando se crea un objeto. Quizás el constructor predeterminado sería el lugar correcto para hacer eso.
fuente
@Column
alrededor. Y también extraño los comentarios establecidos (tomados de Java Doctag).En mi caso, modifiqué el código fuente de hibernate-core, bueno, para introducir una nueva anotación
@DefaultValue
:Bueno, esta es una solución solo para hibernación.
fuente
@Column(columnDefinition='...')
no funciona cuando establece la restricción predeterminada en la base de datos al insertar los datos.insertable = false
y eliminarcolumnDefinition='...'
de la anotación, la base de datos insertará automáticamente el valor predeterminado de la base de datos.insertable = false
Hibernate / JPA, funcionará.fuente
En mi caso, debido a que el campo es LocalDateTime utilicé esto, se recomienda debido a la independencia del proveedor
fuente
Ni las anotaciones JPA ni Hibernate admiten la noción de un valor de columna predeterminado. Como solución a esta limitación, establezca todos los valores predeterminados justo antes de invocar un Hibernate
save()
oupdate()
en la sesión. Esto lo más cerca posible (sin Hibernate estableciendo los valores predeterminados) imita el comportamiento de la base de datos que establece los valores predeterminados cuando guarda una fila en una tabla.A diferencia de establecer los valores predeterminados en la clase de modelo como sugiere esta respuesta alternativa , este enfoque también garantiza que las consultas de criterios que usan un
Example
objeto como prototipo para la búsqueda continúen funcionando como antes. Cuando establece el valor predeterminado de un atributo anulable (uno que tiene un tipo no primitivo) en una clase de modelo, una consulta por ejemplo de Hibernate ya no ignorará la columna asociada donde anteriormente la ignoraría porque era nula.fuente
Esto no es posible en JPA.
Esto es lo que puede hacer con la anotación Column: http://java.sun.com/javaee/5/docs/api/javax/persistence/Column.html
fuente
Si usa un doble, puede usar lo siguiente:
Sí, es específico de db.
fuente
Puede definir el valor predeterminado en el diseñador de la base de datos o cuando crea la tabla. Por ejemplo, en SQL Server, puede establecer la bóveda predeterminada de un campo Fecha en (
getDate()
). Useinsertable=false
como se menciona en la definición de su columna. JPA no especificará esa columna en las inserciones y la base de datos generará el valor para usted.fuente
Necesitas
insertable=false
en tu@Column
anotación. JPA ignorará esa columna mientras se inserta en la base de datos y se usará el valor predeterminado.Ver este enlace: http://mariemjabloun.blogspot.com/2014/03/resolved-set-database-default-value-in.html
fuente
nullable=false
fallará con unSqlException
:Caused by: java.sql.SQLException: Column 'opening_times_created' cannot be null
. Aquí olvidé establecer la marca de tiempo "creado" conopeningTime.setOpeningCreated(new Date())
. Esta es una buena manera de tener consistencia, pero eso es lo que el interrogador no estaba preguntando.