I am auditing a Java object using Hibernate Envers annotations, but initial object creation occurs directly in the database using Pentaho (ETL).
I want to create the object using ETL and add a table entry to the Envers generated object_AUD and REVINFO tables.
I have been trying to find the generation strategy for the REV column from the REVINFO table, but I must be looking in the wrong places. Would someone help me find an effective generation strategy so I can manually insert records into the audited tables without causing possible collisions or weird behavior in the future?
What you seek is going to depend on whether or not you are configuring your application to take the default for org.hibernate.envers.use_revision_entity_with_native_id.
The default value (true) tells Envers to ask Hibernate to create the REVINFO table using a native-based primary key which will either be IDENTITY or SEQUENCE depending upon your database platform. If you look at the table definition for REVINFO in your database, you should be able to deduce this information.
If this property is configured using false, Envers will construct its own sequence metadata and provide that to Hibernate. The sequence is called REVISION_NUMBER and is stored in a table called REVISION_GENERATOR. The sequence is initialized to 1 and incremented by 1 as the default.
Related
I have a large set od data say(7000) of data that needs to to inserted in three tables
say table A,B,C and all having an autogenerated column #id.
Now Table B is dependent on A's auto generated #id .
During batch insert I want to
set a logic so that after a certain threshold the records will be persistent/commit
to the database and I am using hibernate transaction.
Is it possible to get the dependent auto generated id from A's table before it
is been persisted /commit.
Thanks for the reply in advance
Auto-generated IDs in databases that do not support explicit sequences (such as MySQL) are retrieved upon insertion. There is no other mechanism for it, unless you simulate the generation on the Java side and set them there. That, however will not work well if your application ever runs with more than one instance.
I read the discussion about using hbm2ddl.auto=update in order to auto-update changes to the database schema.
The thread is from 2008 and I do not know how secure it is to use the auto-update mode today.
We are running a small JavaEE on a Glassfish with Hibernate 4.3.11 and PostgreSQL. We plan to use continious integration with Jenkins.
Is it useful to work with hbm2ddl.auto=update enabled? Or is it better to use an easy alternative to update/check the updates maybe manually?
I know it is hard to give a blanket statement.
You should not use hbm2ddl.auto=update to update production databases.
Few reasons:
Hibernate will only INSERT missing columns and not modify existing columns. Therefore, if you rename a property (Client to Customer), Hibernate will create a new column Customer, leaving the column Client untouched. You will need to manually "move" the data there and remove the orphan column.
Hibernate will not remove constraints on no longer mapped columns. Thus, if your Client column was NOT NULL, any insert query to that table will now fail in the first place, because Hibernate won't provide any data for the orphan column (Which still has it's NOT NULL constraint) anymore.
Hibernate will not touch data types of existing columns. So, if you change a property type from String to Date - Hibernate will leave the column definition as varchar.
Hibernate does not remove columns of which you deleted the property, leading to data-polution and worst-case (The constraints remain in place) to no longer working applications.
If you create additiional constriants on existing columns - hibernate will not create them, because the column already existed before. (You might miss important contraints on the production db you added on existing columns)
So, perform your updates on your own is safer. If you have to take into account what hibernate is doing and what not - you'd better do it on your own from the scratch.
I'm using Spring Data JPA with Hibernate.
I have a class with a composite key mapped to a database table.
When I perform a save operation using the JPARepository extended interface object, I see the following log in the console:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
Hibernate: insert into RoleFunctionality_Mapping (functionalityId, roleId) values (?, ?)
This is what I see when i repeat the operation with the same data:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
It appears Spring Data first checks whether the Key exists in the database, and then proceeds to perform insertion.
There should be a way to catch the information which hibernate has found (that the database entry/key exists in the database)? How can we check that?
There is no such way. Hibernate can not determine if the primary key exists except it would issue a SQL query itself. Hibernate assumes that this check is done by the application logic to allow this to become a matter of performance optimization.
The only chance Hibernate has to notice of duplicated key problems is a SQLException from the database (or the JDBC layer) informing about a unique constraint violation of the id field. And as always one should consider a Hibernate session as invalid if a SQLException occured (since Hibernate can not ensure a valid state taking interceptor and listener processing into account).
So the spring way of issuing an extra query is the way to go unless you can provide additional logic to ensure the key is not already present in the database by using additional counters, getting and reserving free ids in bulk or using application wide event / messaging solution to synchronize entity id allocation.
Our current database (MySQL) already has Indexes for its foreign keys since these use InnoDB, which (afaik) automatically generates IndexTables for foreign keys. Hibernate wasnt used to create these tables. So my question is: Is MySQL using Indexes for their foreign keys automatically, when I use Hibernate to fetch Data from its tables? Or do I have to configure Hibernate to use these Indexes?
Thank you,
ymene
Yes, the query optimizer decides to use or not to use an index. Use EXPLAIN on your SELECT statements to see what it uses. There is no difference in a query created by Hibernate or a hardcoded query.
Is MySQL using Indexes for their foreign keys automatically, when I use Hibernate to fetch Data from its tables? Or do I have to configure Hibernate to use these Indexes?
There is nothing to configure in Hibernate to make the SQL backend use indices for joins. Let Hibernate perform its queries and if the optimizer decides that using an index is appropriate, it will use it.
PS: I'm not talking about Index Hints syntax here, see HHH-2736 - support for native/SQL query hints in HQL/Criteria (Oracle SELECT hints for example), this is something different.
There is a UNIQUE database constraint on an index which doesn't allow more than one record having identical columns.
There is a piece of code, managed by Hibernate (v2.1.8), doing two DAO
getHibernateTemplate().save( theObject )
calls which results two records entered into the table mentioned above.
If this code is executed without transactions, it results INSERT, UPDATE, then another INSERT and another UPDATE SQL statements and works fine. Apparently, the sequence is to insert the record containing DB NULL first, and then update it with the proper data.
If this code is executed under Spring (v2.0.5) wrapped in a single Spring transaction, it results two INSERTS, followed by immediate exception due to UNIQUE constraint mentioned above.
This problem only manifests itself on MS SQL due to its incompatibility with ANSI SQL. It works fine on MySQL and Oracle. Unfortunately, our solution is cross-platform and must support all databases.
Having this stack of technologies, what would be your preferred workaround for given problem?
You could try flushing the hibernate session in between the two saves. This may force Hibernate to perform the first update before the second insert.
Also, when you say that hibernate is inserting NULL with the insert, do you mean every column is NULL, or just the ID column?
I have no experience in Hibernate, so I don't know if you are free to change the DB at your will or if Hibernate requires a specific DB structure you cannot change.
If you can make changes then you can use this workaround in MSSQL tu emulate the ANSI behaviour :
drop the unique index/constraint
define a calc field like this:
alter table MyTable Add MyCalcField as
case when MyUniqueField is NULL
then cast(Myprimarykey as MyUniqueFieldType)
else MyUniqueField end
add the unique constraint on this new field you created.
Naturally this applies if MyUniqueField is not the primary key! :)
You can find more details in this article at databasejournal.com