I am using this code:
#Column(name = "FECHA_CREACION_TIMESTAMP",columnDefinition="DATE DEFAULT SYSDATE", insertable=false)
#Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacionTimestamp;
But when I insert some data to the table, it doesn't have the date just have the date like null.
Updated Answer: (Now that I know that you are using Oracle)
What you need is to make sure that the column doesn't get included in the insert statements. For that, you need to update your #Column annoation like:
#Column(..other properties.., insertable = false)
See here for more details.
Now, you also need to make sure that the generated value is available in your domain object after you perform the insert. If you are using Hibernate, and do not mind using Hibernate annotations, you can put the following annotation on your field.
#org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.INSERT)
Hibernate will automatically perform the required select query for you.
If you are not using Hibernate, you will need to do a select yourself to fetch the generated value after performing the insert. JPA doesn't have anything to specify that this should be done automatically.
you can use something like :
#Column(name = "FECHA_CREACION_TIMESTAMP",columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP", insertable=false)
#Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacionTimestamp;
Related
I have property in Enum:
#Basic
#Column(name = "payment_status", columnDefinition = "varchar(32) default 'ENTERED'", nullable = false)
#Enumerated(EnumType.STRING)
private PaymentStatus paymentStatus;
I want to get the default value for a field from enum
I have error:
org.hibernate.PropertyValueException: not-null property references a null or transient value
The field cannot be null
The error is when I want to create an object and save in the database without entering this field (PaymentStatus)
EDIT:
#Basic
#ColumnDefault(value = "ENTERED")
#Column(name = "payment_status", nullable = false)
#Enumerated(EnumType.STRING)
private PaymentStatus paymentStatus = PaymentStatus.ENTERED;
Why is it not working?
default 'ENTERED' tells the database to use value 'ENTERED' if the column is not included in the INSERT statement. Since the column is in the class, JPA will always include it in the INSERT statement.
To make JPA fill in the default value, simply assign it with an initializer, so it has that value until replaced by you (calling setter method), or replaced from database (when reading from there).
private PaymentStatus paymentStatus = PaymentStatus.ENTERED;
If you have defined a default in the database and if you want to leave it to the database to set the default value then you need to prevent a null being inserted to that column in the SQL insert statement
You would then need to look at what your JPA provider offers in that area. In Hibernate, for example, you would simply annotate your Entity with #DynamicInsert:
https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/annotations/DynamicInsert.html
For inserting, should this entity use dynamic sql generation where
only non-null columns get referenced in the prepared sql statement?
It should be noted that defining a default in the JPA annotations (as you have done) only has any effect on DDL generation i.e. if you are having your JPA provider generate or update your schema and has to effect on any insert or update operations.
When certain non key fields of a entity are generated in the database (for instance, by triggers) a call to persist will not bring back values that the database has just generated. In practice this means that you may need to refresh an entity after persist or merge (and when level 2 cache is enabled you may even need to evict the entity).
Hibernate have a custom annotation #Generated which handles Generated Properties.
// Refresh property 1 on insert and update
#Generated(GenerationTime.ALWAYS)
#Column(insertable = false, updatable = false)
private String property1;
// Refresh property 2 on insert
#Generated(GenerationTime.INSERT)
#Column(insertable = false)
private String property2;
JPA #GeneratedValue only works with primary key properties.
So, my question is if there is a replacement for #Generated on JPA API (maybe on 2.1)? And if there isn't one, what is the best practice to handle non key database generated fields?
I read the specs from the beginning until the end and it is not such thing, nothing comparable with #Generated, sorry , and as you said.
The GeneratedValue annotation may be applied to a primary key property
or field of an entity or mapped superclass in conjunction with the Id
annotation.
What you could do is use Event Listener #PrePersist and #PreUpdate to set some properties by default or generated by utility classes before em persist the object , try that approach it comes to my mind to something similiar.
I wonder about the behavior of Hibernate regarding fields annotated with #Generated(value=GenerationTime.INSERT) when I do an update on the entity.
I have an entity with the following fields (which are populated by database triggers, the first one on insert, the second one on insert and for each update):
#Generated(value = GenerationTime.INSERT)
#Column(name="created_by", insertable = false, updatable = false)
private String createdBy;
#Generated(value = GenerationTime.ALWAYS)
#Column(name="updated_by", insertable = false, updatable = false)
private String updatedBy;
When I load an entity from the database, both fields are populated - as expected
When I receive the entity back from the web-ui, both fields will be null - as expected since they weren't bound to any form field.
After calling
sessionFactory.getCurrentSession().saveOrUpdate(object);
the createdBy field will be null but the updatedBy field will be set to the correct value (created by the database).
So the entity no longer contains the values from the database - an undesired behavior.
For my situation can solve the issue
- I could change the GenerationTime to ALWAYS - but this seems to be confusing since createdBy is really only set when the entity is inserted.
- I could do a refresh on the entity - but I would like to avoid the extra call.
What is the best practice for the described situation? Are there better options that avoid an explicit call of refresh and don't obscure the semantic of fields modified only on insert?
What are reasonable scenarios to use #Generated(value=GenerationTime.INSERT)?
can you try like this.
#Temporal(TemporalType.TIMESTAMP)
#Generated(GenerationTime.ALWAYS)
#Column(name="create_date", insertable=false,updatable=false)
private Calendar createDate;
I have a Class having two fields
#Column(name = "transactionDate", nullable = true)
private Date transactionDate;
#Column(name = "nextTransactionDate", nullable = true)
private Date nextTransactionDate
--
Both fields can be null. But if transactionDate is not null, then nextTransactionDate must not be null. How can I implement the above relationship between the fields using JPA? Any code snippet, link would be appreciated.
Note: I am using JPA not Hibernate.
You could validate this in your object model or application instead of through database constraints. You may also be able to define your own check constraint in the database through your own DDL script.
It's better to code the biz logic in DAO or service layer instead of defining it in ORM level. JPA and ORM tools is just designed to resolve persistence stuff not biz logic stuff.
In MySQL it is possible to make a TIMESTAMP row being updated on every update operation. Is there a way to realize this for a column with Hibernate and map it to a POJO property?
So that I have something like this:
#Column
private Date updated;
If you want to do it at the database side, you can specify a custom column definition (if schema is generated by Hibernate, otherwise you need to declare it in your schema as desired), and instruct Hibernate that this property is generated at the database side:
#Column(columnDefinition = "TIMESTAMP ON UPDATE CURRENT TIMESTAMP")
#Generated(GenerationTime.ALWAYS)
private Date updated;
Alternatively, you can do it at the application side, as suggested by Jigar Joshi.
You can have this to accomplish this thing
#PreUpdate
protected void onUpdate() {
updated = new Date();
}