Log Creation/Altering of Tables By Envers Hibernate - java

1) When does Hibernate Envers create or alter the audit tables in the schema when there is a new Entity or column that is annotated with #Audited?
2) Is there a way to log the mysql commands that are called when there is a new audit table or column added?

When does Hibernate Envers create or alter the audit tables in the schema when there is a new Entity or column that is annotated with #Audited?
Technically Hibernate Envers does not do this at all, this entire step is handled by Hibernate ORM proper.
During bootstrap of Hibernate ORM, the following steps occur:
ORM gathers all entity mappings, those defined in XML and annotated classes. ORM takes all these representations and builds what we call a boot-model representation of the entities.
Envers implements a special hook that ORM calls into immediately after the boot-model has been prepared but before the runtime model is built which ORM uses thereafter. This hook allows Envers to parse the boot-model in conjunction with the annotated java classes and it creates additional entity mappings for ORM that supplement what was built in (1). These mappings are currently provided to ORM has additional Hibernate HBM XML mappings.
If the hook produces any additional HBM XML mappings, Hibernate ORM integrates those directly by converting them into boot-model representations as well.
Right before Hibernate ORM converts this boot-model into the runtime-model representation, ORM builds a database representation of the mappings. It is at this point that the database model is used during the Schema Migration (if enabled) to validate/update/create the schema to match the database model representation.
Is there a way to log the mysql commands that are called when there is a new audit table or column added?
There are several ways to accomplish this, some are easier than others of course.
For example, you could enable Hibernate SQL logging, configure those entries to be written to a special named file using your logging API of choice and then ship those logs off for post-processing on defined intervals.
You could also consider using something more standalone such as Debezium that is capable of monitoring database changes at the transaction/archive/oplog/binlog level and for certain connectors exposes a Kafka topic that specifically stores DDL changes.

Hibernate-envers is using interceptors to insert changes into audition-tables. They are called right before the transaction is committed to the database.
The question is a little bit unclear, if you say mysql-commands I guess you mean update-queries like CREATE TABLE and CREATE COLUMN. By default, enver is reporting violations against the schema. I can imagine that - if you expose the audition-tables as hibernate-entitys aswell - a hbm2ddl might create those create-table and create-column update-queries.
After all I suggest to use the single-source-of-version-of-truth concept (SSOVOT) and failfast (FF) and dare the database as the single-point-of-faliure (SPOF).
The wording problem
Yes, the hibernate-plugin is called enver, but from an scientific pov a enver(entity-version) is only the version-property marked with #Version in the entity. The correct name is audition because you historically log all changes to the table in the database.
In case of "change entity tables" having rows already.
First to say is that every payload-column in entity-tables is nullable, you must add a column in the audition-table it has by default a null value. But if the genuine table does not allow to have null-values in the colmn the audition is broken! This will lead to unexpected problems. This means that the automated replication of genuine-columns to audited-columns must be an process of reconstruct schema AND DATA.

Related

"spring.jpa.hibernate.ddl-auto" property is used for migration?

I am not sure about question since i am not familiar concept of migration exactly. I have just known this is used for updating database without deleting tables manually from database console. Since I have known this as I mentioned, I think like that, If I set this property to "create-drop", I can achieve migration. Am I correct? Can anyone explain it to me or advice any reference?
For the record, the spring.jpa.hibernate.ddl-auto property is Spring Data JPA specific and is their way to specify a value that will eventually be passed to Hibernate under the property it knows, hibernate.hbm2ddl.auto.
The values create, create-drop, validate, and update basically influence how the schema tool management will manipulate the database schema at startup.
For example, the update operation will query the JDBC driver's API to get the database metadata and then Hibernate compares the object model it creates based on reading your annotated classes or HBM XML mappings and will attempt to adjust the schema on-the-fly.
The update operation for example will attempt to add new columns, constraints, etc but will never remove a column or constraint that may have existed previously but no longer does as part of the object model from a prior run.
Typically in test case scenarios, you'll likely use create-drop so that you create your schema, your test case adds some mock data, you run your tests, and then during the test case cleanup, the schema objects are dropped, leaving an empty database.
In development, it's often common to see developers use update to automatically modify the schema to add new additions upon restart. But again understand, this does not remove a column or constraint that may exist from previous executions that is no longer necessary.
In production, it's often highly recommended you use none or simply don't specify this property. That is because it's common practice for DBAs to review migration scripts for database changes, particularly if your database is shared across multiple services and applications.
The possible values for the “spring.jpa.hibernate.ddl-auto” configuration property are the following ones:
none - No action is performed. The schema will not be generated.
create-only - The database schema will be generated.
drop - The database schema will be dropped.
create - The database schema will be dropped and created afterward.
create-drop - The database schema will be dropped and created afterward. Upon closing the SessionFactory, the database schema will be dropped.
validate - The database schema will be validated using the entity mappings.
update - The database schema will be updated by comparing the existing database schema with the entity mappings.
These are some of the basic things to be known,
validate: validate the schema, makes no changes to the database.
update: update the schema.
create: creates the schema, destroying previous data.
create-drop: drop the schema when the SessionFactory is closed explicitly, typically when the application is stopped.
none: does nothing with the schema, makes no changes to the database
These options seem intended to be developers tools and not to facilitate any production level databases.

Linking entities to existing tables without code

Let's assume that we have java entities already implemented and annotated with Jpa annotations.
We also have an existing database slightly different to the schema described by said entities.
How I can link the data base with my entities without the code?
Otherwise, how can i proceed from the begining when implementing my entities to make this stuff configurable ( give the user the possiblity of specifying the names of the columns corresponding to the fields of each entity in an externalized configuration file)?
NB: I use hibernate as an ORM.
I believe this is what you are looking for

Configuring Hibernate to play nice with existing DB constraints?

The last few days I've rolled up my sleeves and dug into Hibernate for the first time. I was very surprised to learn that Hibernate's default behavior is to actually drive the DDL of the database itself:
<property name="hbm2ddl.auto">create</property>
or
<property name="hbm2ddl.auto">update</property>
This is opposite of what I'm used to, where someone (usually a DBA) creates the database structure: the schemas, the table, the key constraints, the indexes, triggers, etc; and then I (the developer) code my app to abide those constraints.
This raises a few similarly-related questions:
How are indexes created/maintained in conjunction with a Hibernate-based app? Pick your favorite relational DB - MySQL, Postgres, Oracle, anything. Do you specify indexes through Hibernate (and if so, how), or do you have to specify them in the DB (and if so, how do you get Hibernate to honor such indexes and not overwrite them)?
Same question as #1 above, but with multi-column keys instead of indexes.
How do you specify column order in Hibernate? Is it just based on the order of the Java fields inside the entity? What about columns that Hibernate adds (such as when doing joins or implementing inheritance strategies)?
If I manuall install a trigger on a table that Hibernate created, how do I prevent Hibernate from overwriting/deleting it?
How do I specify what DB/schema a Hibernate table gets created in?
Thanks in advance!
You can use #Index annotation on your entity field
Please see this question / answer: How to define index by several columns in hibernate entity?
Yes it's just based on the order of Java fields in the entity
You can set hbm2ddl.auto to "validate" to make it just validate your schema, without making any updates.
You can use #Table(name = "..") annotation to specify custom name for your entity/table

JPA2/Hibernate - Creating a schema on the fly (ie without pre-create the schema manually)?

I use JPA 2 with Hibernate Entity Manager 3.6.4. Once I have marked my entities with various annotations (#Entity, #MappedSuperClass etc), I put in my persistence.xml file the default schema to use (hibernate.default_schema property).
I know it's possible to create automatically the objects contained in the schema.
But is it possible to create the schema itself automatically and then create the objects it contains ?
EDIT :
I use this parameter too : hibernate.hbm2ddl.auto, to tell Hibernate to create the schema if it doesn't exists yet. No luck, Hibernate doesn't create it !
I have googled a little bit and find this post : Hibernate hbm2ddl won't create schema before creating tables.
The fact that Hibernate does not create a schema before creating table is a bug. Other database suffer from this situation : H2, Postgresql etc.
This bug is planned to be fixed with 5.0.0 release of Hibernate.
So, for now, the only workaround is to create the schema by yourself, either manually or by a mean offered by your database vendor, since Hibernate can't do it itself :\
I managed to build a workaround that uses the hbm2ddl default flow.
Since it always calls the "database-object" drop statements BEFORE creating schema, you can do something like this:
<database-object>
<create></create>
<drop>DROP SCHEMA IF EXISTS myschema cascade; CREATE SCHEMA myschema</drop>
</database-object>
unfortunately the create clause is mandatory and sadly it's only executed AFTER schema creation, no matter what order you put it on cfg.xml, so I made it empty, that way you don't have errors trying to creating schema again (it was already created together with drop)

Will hibernate java programs have no sql code?

I haven't worked with hibernate. I have little bit of experience in java. I was going through source of a beast of an java application created by Oracle(Retail Price Management). I was expecting a lot of sql code embedded in there as the application makes heavy use of database. But to my surprise, NO embedded SQL code! so far. I found that it was using what is called as "Hibernate" from the lot of .hbm.xml files. Is it a trademark for java programs using hibernate or maybe I haven't seen the complete codebase?. Could someone enlighten me how this is possible?. Thanks.
Hibernate, as all ORM tools, indeed lessens or eliminates the need to use raw SQL in Java code, due to the following:
many associations between various entities are recorded in the Hibernate mapping, so these are fetched automatically by Hibernate - i.e. if you have an aggregation relationshiop between two classes on the Java side, this may be mapped as a foreign key relationship in the DB, and Hibernate, whenever an instance of class A is loaded, can automatically load the associated instances of class B too,
many queries can be done in Hibernate's own HQL query language, or using its Criteria API.
Under the hood Hibernate does generate SQL to communicate with the DB, but this is not visible on the Java side. It can be seen in the logs though, if it is enabled.
Due to this, programs using Hibernate very rarely need to use JDBC or SQL directly. The exceptions are typically ralted to "tricky" legacy DB schemas which can't be fully handled by Hibernate.
Because that's the whole purpose of using Hibernate or any other object-relational mapping framework.
Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions.
Hibernate generates SQL for all its standard database operations. It understands different SQL dialects, and the mapping files (.hbm.xml) tell it about the database structure so it knows how to construct its queries. There is a showSql setting you can turn on if you want to see it outputting its generated SQL as it runs.
Hibernate is an Object-Relational Mapper (ORM). ORMs are used to hide the ugly details of SQL incompatibility[sic] between databases from your program -- you define your tables and map them to an object hierarchy (the .hbm.xml files) and then Hibernate does the rest. Thus most programs that use Hibernate won't see a single phrase of SQL, unless there's a specific reason to execute a complicated query.
Hibernate is a tool, or technology that takes care of the interaction between the database and application for you. You have to tell the structure of the application and the database to it, this is what is in the .hbm.xml files.
The SQL is generated by Hibernate at runtime (kind of)
Say you have an Fruit class, and objects of this is persisted into a T_FRUIT table.
You say this to hibernate, via the .hbm.xml files. That there is a table T_FRUIT, this table is represented by the Fruit class, and which fields in the Fruit class correspond to which columns in th T_FRUIT table.
And then it knows whenever you are trying to save a fruit, it should insert/update to the T_FRUIT table.
When you want to create an Apple, you create an object of fruit corresponding to apple and save "save this fruit".
Hibernate takes care of persisting it.
You can have relationships defined between tables, and Hibernate is intelligent enough to persist in multiple tables.
When you fetch a fruit, hibernate fetches the details of the fruit and its children also(data from referencing tables). And you can say whether you want fetch all the children
at once, or as and when required.
And so on. Aim is to make your life easier, and code maintainable, easy to read, portable,...
With this info, let me redirect you.

Categories