Hey guys how can I use #version annotation but instead of replacing the modified data add a new row with the same identifier and the incremented version in the database.
For example here the id 173 is duplicated the only change is the version, that's my goal.
enter image description here
#Version is intended for optimistic locking and should not be used for this.
As Taylor commented you can use Hibernate Envers for something really similar. It will result in a separate table containing all your versions, while the main table that you map your entity to still has only the current version.
If you want all these entities to be actually in the same table you should just make the existing id plus an additional version field the id and then copy the entity and update the version before changing it. Version field here means a normal probably numeric field that you use as version it must not be annotated with #Version.
If you really want to abuse the #Version attribute you could create a trigger on the underlying table that creates a new row on every update.
Related
I built a jpa-entity on top of a database view.
The #Version field is mapped to the revision of the table the view is set up upon.
However, when the underlying table row changes, I do net get the update in my view-entity.
When I select the table row directly, I see that its revision changed.
How can I force two request against an entity based on an sql-view to use the latest data and not a cached state?
It turned out my problem occurs only in test ... when I read-modify-read an entity in the same test method, I have to manually refresh it in between, when I do a rest itest against the application, the latest values are returned ... so nothing to do here
I have some Hibernate code running against a Postgres 9.5 DB, which looks like roughly like below (anonymized) -
Integer myEntityId = myEntity.getId();
getCurrentSession().evict(myEntity);
myEntity.setId(null);
MyEntity clonedMyEntity = (MyEntity)getCurrentSession().merge(myEntity);
myEntity.setMyBooleanField(false);
getCurrentSession().save(myEntity);
I have an entity myEntity with a large number of fields. I want to create a duplicate of the record with only 1 field value changed. To achieve this, I evict the entity from session, set Primary Key to null, merge it back to session, set the field I want to change, and then save the entity to DB. However, this code (which was working correctly for some time), is not working now. It sees incorrect value for the boolean field I am trying to modify - as a result violating some database constraints. Please help me fix this or suggest a better way to achieve what I am trying.
The error was happening not on adding this record but on add of another record to an audit table, triggered by the addition of this record. A coworker suggested me to use Eclipse Breakpoint view and use the add breakpoint option there and select the ConstraintViolationException class - this helped me to see the error for which trigger was failing and why and accordingly modify the data to suit the database constraint.
I have a question about Postgres and GenerationType.Identity vs Sequence
In this example...
#Id
#SequenceGenerator(name="mytable_id_seq",
sequenceName="mytable_id_seq",
allocationSize=1)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator="mytable_id_seq")
I understand that I am specifying a Postgres sequence to use via annotations.
However, I have an id column defined with the 'serial' type, I have read that I can simply use GenerationType.IDENTITY and it will automatically generate a db sequence and use it to auto increment.
If that's the case, I don't see an advantage to using the SEQUENCE annotations unless you are using an integer for an id or have some specific reason to use another sequence you have created. IDENTITY is alot less code and potentially makes it portable across databases.
Is there something I'm missing?
Thanks in advance for the feedback.
If you have a column of type SERIAL, it will be sufficient to annotate your id field with:
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
This is telling Hibernate that the database will be looking after the generation of the id column. How the database implements the auto-generation is vendor specific and can be considered "transparent" to Hibernate. Hibernate just needs to know that after the row is inserted, there will be an id value for that row that it can retrieve somehow.
If using GenerationType.SEQUENCE, you are telling Hibernate that the database is not automatically populating the id column. Instead, it is Hibernate's responsibility to get the next sequence value from the specified sequence and use that as the id value when inserting the row. So Hibernate is generating and inserting the id.
In the case of Postgres, it happens that defining a SERIAL column is implemented by creating a sequence and using it as a default column value. But it is the database that is populating the id field so using GenerationType.IDENTITY tells Hibernate that the database is handling id generation.
These references may help:
http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators
https://www.postgresql.org/docs/8.1/static/datatype.html#DATATYPE-SERIAL
From "Pro JPA2" book:
"Another difference, hinted at earlier, between using IDENTITY and other id generation strategies is that the identifier will not be accessible until after the insert has occurred. Although no guarantee is made about the accessibility of the identifier before the transaction has completed, it is at least possible for other types of generation to eagerly allocate the identifier. But when using identity, it is the action of inserting that causes the identifier to be generated. It would be impossible for the identifier to be available before the entity is inserted into the database, and because insertion of entities is most often deferred until commit time, the identifier would not be available until after the transaction has been committed."
I think it can be helpful if you are using the same sequence for more than one table (for example you want a unique identifier for many types of bills) ... also If you want to keep track of the sequence away from the auto generated key
You can find here the solution of updating the PostgreSQL table creation accordingly, in order to work with the GenerationType.IDENTITY option.
I am trying ORMLite as an ORM for a project I am developing. I am mapping a java class to a table that has some auditing fields (ie. updatedby, updatedtime, etc.). The auditing fields are maintained by the database using triggers to ensure that no matter what front-end the user is using these fields will always be correctly updated when a record is updated.
I need to include these fields in my client application to inform the user when the record was last updated, but the user can't change them. Is there a way to annotate the class so that ORMLite won't try to perform updates on these fields or include them in insert statements. The database will deny an update if these fields are included in an update statement (which is why I can't just write back the original value that was queried from the database).
I tried using the #DatabaseField(persisted = false) annotation on the Java fields, but then they don't get queried at all so the Java object is never populated with these fields.
Basically, I need these fields to be included in SELECT statements, but not included in INSERT or UPDATE statements (equivalent to a #DatabaseField(immutable = true) annotation).
Interesting pattern. ORMLite didn't support the feature at the time but now it does as of version 4.46.
There is now a #DatabaseField(readOnly=true) annotation field.
Using Entity Framework CodeFirst, how do I create a created datetime column that gets populated with the current timestamp everytime a record is inserted for that table, and a modified datetime column that has a timestamp generated evertime a row is updated? Rails does this by default and I was hoping the EF generated database would have this as well, but it doesn't. Is this something that can be done with data annotations? If so, how?
Thanks!
It is not supported in EF. EF will not create these columns for you automatically. You must do it yourselves by either:
Have Created and Modified properties in every entity where you want to maintain these values. You must also manually maintain these columns in your application (common approach is overriding SaveChanges and set values accordingly).
If you don't need these values mapped (you never expect to use them in your application and you are happy with the logic in the database) you can create custom database initializer which would execute your custom SQL to alter tables and add those columns, default constraints for Created columns and update triggers for Modified columns.