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
Related
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.
Working with Hibernate, I noticed that all of the Java objects going into persistence are defined in a mapping file. Is there a way to only depend on the annotations instead of a separate .xml for this? At the time of creation, we do not know what the object that is to be persisted contains. We know it is primitive data types, Strings, ints, floats/doubles, but we do not know how many of each field the object may contain until the same time it needs to have a table created for it to be entered into the db.
Note that Hibernate is just the first ORM solution that I've looked at. I am not tied to it if there is another ORM solution that solves this problem.
I think in your use case, you can use Dozer mapping for managing beans without having explicit definitions of class files and this can ben loaded at runtime using spring annotatons dependency injection.
You may look into JDX ORM for Java. The mapping is defined declaratively in a text file but just a minimal specification is needed for each class - its name and the names of the primary key attributes. Other attributes are automatically picked up by JDX. So you may continue to modify your class without making any further changes to its mapping specification. Disclaimer: I am the architect of JDX ORM.
In our project we have a constraint of not having the luxury to alter the table structure already in place. The tables are highly denormalized in nature.
We have come up with good POJOs for the application. We have the Entity beans generated out of the exiting tables. Now we have to map the POJOs to the entities so that we can persist.
Ultimately, we combine a good POJO with a bad table. Any thoughts on options/alternatives/suggestions to this approach?
Hibernate/JPA(2) has a rich set of functionality to manipulate the mapping (so that your objects can differ from the tables), so that many (NOT ALL) old tables can be mapped to normal object. -- May you should have a look at this first, any use your pojo/table-"solution" only if this mapping is not powerful enough.
If you have a read only application, you can think of using views to make your table/views more like you objects. This may reduse the amount of strange mapping.
I don't know your mapping, size of the application or use case, but have you considered not to use Hibernate? I ask this, because I can imagine (how I said: I don't know you application), that in a architecture like this, no Hibernate feature is used and so Hibernate will add only a not needed complexity.
If you are using Hibernate you should be able to map your POJOs to the table structure using only XML files, without creating new Java beans. This would allow you to easily change the mapping if all of a sudden you can change the tables structures and make the economy of intermediary beans. That's the best you can do.
There's an enterprise application using Java + Hibernate + PostgreSQL. Hibernate is configured via annotations in the Java source code. So far the database schema is fixed, but I faced the problem that it needs to be dynamic:I can receive data from different locations and I have to store these in different tables. This means that I have to create tables run-time.
Fortunately, it seems that all of these data coming from the different institutes can have the same schema. But I still don't know how to do that using Hibernate. There are two main problems:
How to tell to Hibernate that many different tables have the same structure? For example the "Patient" class can be mapped to not just the "patient" table, but the "patient_mayo_clinic" table, "patient_northwestern" table, etc. I can feel that this causes ambiguity: how Hibernate knows which table to access when I do operations on the Patient class? It can be any (but only one) of the former listed tables.
How can I dynamically create tables with Hibernate and bind a class to them?
Response to suggestions:
Thanks for all of the suggestions. So far all of the answers discouraged the dynamic creation of tables. I'll mark Axel's answer, since it achieves certain goals, and it is a supported solution. More specifically it's called multi-tenancy. Sometimes it's important to know some important phrases which describes our problem (or part of our problem).
Here are some links about multi-tenancy:
Multi-tenancy in Hibernate
Hibernate Chapter 16. Multi-tenancy
Multi-tenancy Design
EclipseLink JPA multi-tenancy
In real world scenario multi-tenancy also involves the area of isolating the sets of data from each other (also in terms of access and authorization by different credentials) once they are shoved into one table.
You can't do this with Hibernate.
Why not extend your patient table with an institute column?
This way you'll be able to differentiate, without running into mapping issues.
I am afraid you can't do this easily in Hibernate. You would have to generate the Java source, compile it, add it to your classpath and load it dynamically with java.reflection package. If that works, which I doubt it, it will be an ugly solution (IMHO).
Have you consider using a schema less database i.e: NoSQL databases or RDF
databases. They are much more flexible in terms of what you can store in them , basically things are not tight up against a relational schema.
In most environments it is not a good idea to create tables dynamically simply because dbas will not give you the rights to create tables in production.
Axel's answer may be right for you. Also look into Inheritance Mapping for Hibernate.
I agree that its not advisable to create tables dynamically nevertheless it's doable.
Personally i would do as Axel Fontaine proposed but if dynamic tables is a must-have for you I would consider using Partitioning.
PostgreSQL allows you to create ona main table and few child tables (partitions), records are disjunctive between child tables, but every record from any child table is visible in parent table. This means that you can insert rows into any child table you want using just simple insert statement (its not cool but has the same level of complexity as composing and persisting an entity, so its acceptable in your case) and query database using HQL
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.