Generate Hibernate Envers primary key manually and jpa as well - spring-data-jpa

My project is migrating from Grails to Java so I have exisiting Audit data in a single table pushed by Grails Audit plugin, now I am using Java envers for Auditing in java. I have below doubts:
-> If i want to push data from single table to different Audit tables(in Java) manually, how can i generate Primary key of revision table for history data manually which will not collide with primary key generated from Java annotation?
As for new entries I am generating primary key like below:
#Id
#GeneratedValue
#RevisionNumber
#Column(name = "ID") #NotNull
private Long revisionId;
-> Any other way to push data from single audit table to segregated Audit tables(In java) instead of doing it manually?
Please let me know about this.
Thanks.

Envers should be creating sequence named REVISION_LISTENER on Oracle.
Therefore you should be able to use Oracle's syntax SELECT REVISION_LISTENER.NEXTVAL in order to get the next sequence value and use that in the REV field both in your audit table and the revision entity info table too.
This only applies to DefaultAuditStrategy.
If you intend to use the ValidityAuditStrategy, there are other fields which you'll have to understand the internals of Envers in order to be able to populate the relevant fields. If you are using this strategy, let me know and I'll add more details that are specific to it, but its very complex and quite tedious.

Related

Setting JPA behavior for importing entities from tables

How can I tell JPA how to behave with different column types in my database when it tries to generate the entities from tables?
For example when I have a column like the following in my MySQL:
`deleted` tinyint(1) NOT NULL DEFAULT 0,
I want in the generated entity by JPA have boolean instead of byte, but what the JPA will generate is something like this:
#Column(nullable=false)
private byte deleted;
However I want to have something like this:
#Column(nullable=false)
#Type(type = "org.hibernate.type.NumericBooleanType")
private boolean deleted;
I think there must be a way that I tell JPA how to translate the column types in my tables in the entities in Java!?
I don't like to modify the entities by hand!
If you're asking how to configure the Eclipse wizard to map TINYINT onto boolean, the answer is you probably cannot.
Using Hibernate tools looks more promising, though. There's a hibernate.reveng.xml config file you can use to control type mapping.
As a side note:
I don't like to modify the entities by hand!
Note that reverse engineering tools in general lack the business knowledge required to generate a business model structure that is completely sensible. You will likely have to do some tweaking (e.g you likely won't get any #ManyToMany associations, even if they are the more natural solution domain-wise).
In the last page of that wizard we can define the expected type for each column. The interesting part is, eclipse stores somehow the selected types for each column and in the future when you try to regenerate the entities you don't need to do this step times to times!

Why and how hibernate_sequence is using for id generatior

I'm faced out an issue with ID generation for my entities generated by JHipster:
Dev environment on H2 database
Prod environment on Postgres
I have one entity "station" with two fields "id" and "name"
Creating a liquibase script which imports dictionary in "station" table like
INSERT INTO station (name) VALUES ('Adygeya') without ID definition
Trying to add station on dev environment - OK
Trying to add station on prod - Hibernate tries to add new station with duplicated ID
WHY?
My research was shown that only for postgres and oracle in initial scheme jhipster created a new sequince "hibernate_sequence" which is used for new entities creation.
So I'm fixed out this wrong behaivour by adding specific sequence name for my entity ID generation rule
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "station_gen")
#SequenceGenerator(name = "station_gen", sequenceName = "station_id_seq")
private Long id;
Now I have just 3 questions:
Why JHipster using one sequince for all tables for postgres and oracle?
Where is it configured?
What am I doing wrong?
Will post here my answer wich was found with help of #GaƫlMarziou and #Julien Dubois.
Thats because of history and default behaivour of Hibernate hilo algorithm with GenerationType.AUTO. MySQL doesn't support sequencies so JHipster needs to use this stupid algorithm
JHipster team has found right solution wich will fix my problem. The solution is to use GenerationType.SEQUENCE for all DB but use GenerationType.IDENTITY for MySql. All the details in this commit https://github.com/jhipster/generator-jhipster/commit/4516b4ff4d49a96a75fd963b0c7667f198bd9b79
This way I will configure my entities now too.

JPA and PostgreSQL with GenerationType.IDENTITY

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.

Auditing #ElementCollection/#Embeddable with hibernate-envers

I'm trying to audit a collection of #Embeddable objects using hibernate-envers.
According to https://hibernate.atlassian.net/browse/HHH-6613 support for auditing #ElementCollection was added. This feature doesn't seem to work well: when trying to save several #Embeddable objects with the same revision number NonUniqueObjectException is thrown.
Does anyone have a working example of #ElementCollection+#Embeddable audited with Envers?
As of Hibernate 5.2.8, we managed to make it work by these steps:
Define the java type as Set for the collection of embeddable elements
Implement hashCode() and equals() methods in the class of the embeddable elements
Be sure to create an int column named SETORDINAL in the table that holds
the audit log of said elements (or let hibernate create the tables for you
by setting the appropriate configuration key).

JPA Relation or Secondary Table

I am reengineering one of my project with JPA which was initially on iBatis.
public class Entity{
//ids and other stuff
String locale;
String text;
}
I was storing locale and text into separate table, which can be achieved via secondary table in JPA.
I am not able to create secondary table with its own ids besides Join
id?
how can I achieve it? If possible then it raises the following
question:
how would I retrieve it back if I create an entity object with locale set to user settings
See,
http://en.wikibooks.org/wiki/Java_Persistence/Tables#Multiple_tables
Otherwise include your exact schema and model and issue.