Mapping Multiple tables to Single Entity - java

I have a Database that contains multiple tables which are generated on a per month basis. e.g
Transaction_01_2014
Transaction_02_2014
Transaction_03_2014
.
.
.
Transaction_12_2014
All the tables have the same structure. The only difference is the month and year appended at the end.
Is it possible to map all these tables to a single #Entity class "Transaction" in Hibernate? if yes, do I need to change some configurations? If its not possible this way, how should I operate on these tables in an subtle and simple manner, from my java application?
Cheers!

Yes. You can map multiple tables to a single #Entity class using #MappedSuperclass annotation. By creating a super with this annotation & inheriting it's feature to all sub-classes with different tables in #Table annotation. But, in this case problem of normalization arises.
OR
You can use #SecondaryTable annotation which allows you to specify one or more secondary tables indicating that the data for the entity class is stored across multiple tables.
For more information :
#MappedSuperclass - Java Doc Example
#SecondaryTable - Java Doc Example
Tutorial - Map One POJO To Multiple Tables

If the purpose of this new entity is to read and not for insert, update and delete, like reporting and monitoring then following the approach may help you:
You may create a database VIEW that unions-all these tables.
Having the new #Entity class mapped to these VIEW will solve the problem.
The View's definition(DDL) needs to be updated by a database job
(side by side of tables generation per month )

Related

Is there better solution to map lots of fields entity into two tables?

I am getting data with 50 fields. How to map into two tables in jpa, in which I required only three fields and rest of fields I need to only pass to downstream?
This is for a new spring data jpa, running H2 db project. In the past, I’ve tried to map all 50 fields in one entity table. But I require only 3 essential fields from those 50 fields to process of last 5000 records from db.
#Entity
class SingleCustomer{
//ID field
// 3 fields only these fields I am using to process my data from db
//47 fields just to pass to another service without any process
}
To improve performance of my application which approach I should take?
Are there any other ways to improve application performance like split into two entities and join on one to one when needs to send another service.
As you said you can split all the fields into two entities and join on one-to-one relationShip. But you should notice that field with one-to-one relationShip is loaded eagerly by default, you should mark it as lazy-loaded to improve performance.
Using a separate entity for fields you don't need together with a #OneToOne association is one way of doing that, as #Lebecca pointed out.
However, if you'd rather keep all the properties in one entity, you could turn on Hibernate bytecode enhancement, which enables support for #Basic(fetch = LAZY). If you want, you should also be able to combine such an approach with using a #SecondaryTable to store the properties you don't usually need.
See here for more info, including info on how to fine-tune the lazy loading behavior with enhancement enabled.

Create multiple tables with same domain in jpaRepository

I have one #Table domain and want to create multiple tables using that. How can I do it with JPARepository.
#Table
public class structure implements Serializable{
...
}
I want to create a lot of tables with different names and same structure in run time and save records to them.
How can I do this with JPARepository?
Creating JPA mapped classes dynamically is not possible. But there are possibles to minimize the code you have to write.
MappedSuperClass
Create one class annotated with MappedSuperclass and let all other classes inherit from it. This way the actual mapped classes contain very little code.
Inheritance
You mentioned in the comments that your classes are different types. This suggests that maybe inheritance with a table per class is the correct way to go.
Again create a superclass with all your proper classes to inherit from, but this time annotate them as with #Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
Partitioning
You write in the comments
Because I'm working on a large amount of data and if I insert all of them in one table my query performance is low.
Which makes me think you might be approaching this on the wrong level and you should really look into partitioning. The availability of this and how it exactly works depends on the database you use. Therefore I just leave a link to Wikipedia.

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

JPA - Redirect one entity Update/Delete statements to a mirror table

I am working with Java EE 7 on a Wildfly server. I have a strange scenario, where the client has two tables - "employees" and "employees_modified". The second table has the exactly same structure as the first one and servers as a modification storage. So if an employee changes his name from "john" to "john-1", we will write to employees_modified
insert into employees_modified(first_name) values("john")
Please note that the other fields in the table "employees_modified" are empty.
The question is: is there a way to somehow map the two tables and overwrite the values from employees by those in employees_modified where they are present.
I looked at #Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) and #AttributeOverrides but those solutions don't seem to fit to my scenario.
Look at hibernate envers, it solves your problem simply. Attach envers to your project. Place the first table under audit with annotation #Audited and #AuditTable(value = "employees_modified"). But as pointed by #Predrag Maric it is important to leave other fields of the second table empty, you can use #PostPersist (or listener in pure hibernate) method in entity. In this method you can describe additional logic employees_modified entity creation and persisting.
You can use #SQLUpdate and #SQLDelete to customize the CRUD statements to be redirected to a different table:
#Entity
#SQLUpdate( sql="UPDATE employees_modified SET name = ? WHERE id = ?")
#SQLDelete( sql="DELETE FROM employees_modified WHERE id = ?")
public class Employees {
...
}
If it's only for auditing, I agree with the answers before me (triggers, events etc).
If you actually want to access that "employees_modified" table (e.g. run complex Hibernate queries) than you can use a second persistent unit. The following post: https://developer.jboss.org/thread/237078 seems to indicate that's a recommendation from hibernate. Obviously the 2nd unit will need xml configuration rather than annotation - at least it can't rely on the same #Table annotation.
BTW there's also some documentation about a #SecondaryTable annotation, but it's my understanding that it doesn't match your case (because your business probably needs to treat those tables differently - sometimes you want to view just the history, sometimes just the live data)/

How does Envers deal with schema changes?

I am thinking about switching from a self-implemented versioning-solution to Hibernate Envers, but I am not quite sure yet. I have read a lot about it, but I am concerned about schema changes and how Envers deals with them after having historized data according to an older schema.
What is your experience with Envers in this regard? How do you deal with schema changes and existing data with Envers?
Update 1:
It is not just about adding removing simple columns from a table, but e.g. when changing a simple Forein-Key-Relationship into a separate entity with two 1:n-relationships (M2M with attributed columns. This is a "logical" change in your data model. How do you deal with that when using Envers, when there is already historized data according to the old model? Is there an alternative to manually write sql-scripts and transfering them into the new representation?
In my experience, Envers simply copies every field from your entity table to its audit tables. The copied fields in the audit tables have no constraints on them, including nullability and foreign key constraints, so there's no problem with adding or removing such constraints on the real tables. Any kind of relationships you add to your entities will just be new audit columns and/or tables added under Envers, and it's up to you to correctly interpret them in their historical context.
For your example, if I understand correctly, of switching from a join-column-based relationship to a join-table-based one, you'd simply have the old join column coexisting with the join table, and at the point of the cutover, the former will cease being populated in favor of the latter. Your history will be completely preserved, including the fact that you made this switch. If you want all the old data to fit into the new model in the audit tables, it's up to you to do the migration.
There shouldn't be problems with modifying the existing schema as Envers relies on your #Entities to create the audit tables. So if you add or remove a column from an existing table, as long as this change is reflected in your #Entity / #Audited JavaBean, it should be ok.
The foreign key refactoring should be fine with Envers. As Envers creates a join table even for one-to-many relationship, it should be straight to change it to become many-to-many relationship. I extracted one paragraph from official document:
9.3. #OneToMany+#JoinColumn
When a collection is mapped using these two annotations, Hibernate
doesn't generate a join table. Envers, however, has to do this, so
that when you read the revisions in which the related entity has
changed, you don't get false results.
To be able to name the additional join table, there is a special
annotation: #AuditJoinTable, which has similar semantics to JPA's
#JoinTable.
One special case are relations mapped with #OneToMany+#JoinColumn on
the one side, and #ManyToOne+#JoinColumn(insertable=false,
updatable=false) on the many side. Such relations are in fact
bidirectional, but the owning side is the collection (see alse here).
To properly audit such relations with Envers, you can use the
#AuditMappedBy annotation. It enables you to specify the reverse
property (using the mappedBy element). In case of indexed collections,
the index column must also be mapped in the referenced entity (using
#Column(insertable=false, updatable=false), and specified using
positionMappedBy. This annotation will affect only the way Envers
works. Please note that the annotation is experimental and may change
in the future.

Categories