Use Hibernate to persist and query multiple-object relationship [duplicate] - java

This question already has answers here:
Which annotation should I use: #IdClass or #EmbeddedId
(7 answers)
Closed 2 years ago.
what's better for JPA/Hibernate composite primary keys, #IdClass or #EmbeddedId implementations and why?
This is an intentionally naive question. I decided to use #EmbeddedId (for whatever reason) and I feel like I made the wrong choice. Dereferencing the embeddedId that contains the column properties is redundant and quite error-prone when coding.
Are there any more reasons for and/or against the other? Is the a recommendation by the JPA (spec)?

First, if possible, avoid composite ids at all costs. But if you really need, I would recommend #EmbeddedId.
#IdClass is basically a leftover from EJB 2.1 times to make it easier from migrating from BMP. In some other rare corner cases it may be better than #EmbeddedId too. However, generally #EmbeddedId is better and more OO since it encapsulates the concept os the key much better in the object.
You may want to use #AttributeOverride(s) if you need in the key field.
I don't see why do you think that dereferencing the embedded id is redundant and error-prone.

As Pascal wrote here's part of the answer:
Which annotation should I use: #IdClass or #EmbeddedId
In the end, I believe using #IdClass is much easier in practice, because you have to add the embeddedId property name to dereference PK properties, while these aren't written for all non-PK properties.
You always have to remember exactly which properties are part of a PK and those which are not. That complicates writing JPQL queries unneccessarily.
Also, AFAIK the JPA 2.0 spec allows you to put #Id onto #XToX/#JoinColumn/s properties and it introduces the #MapsId annotation, so that mapping identifying relationships (a.k.a. derived identifiers in JPA) are more natural to implement.

I. Remember using idclass to do it. But I'd recommend doing everything you can to avoid multi field keys. They just create extra work.

Related

Object equality/hashcode vs JPA/Hibernate entity equality/hashcode

After reading a bit on the topic, I am a bit lost on the Hibernate/JPA requirements for #Entity equality. Do I really have to adjust my #EqualsAndHashCode to make my entities equal based on the db uniqueness still in 2020? What's the point of the #Id metannotation then?
I need to be able to compare my entities at object level, so for now I just implemented my EqualsAndHashCode according to all fields besides #Id.
What are exactly the problems I can face if I keep on with that approach? Isn't anyway the db gonna throw an exception if for some reason Hibernate tries to store or mix 2 entities that have same #Id but are not equals with my implementation? Is it really a risk? I am pretty sure Ive seen in the past a lot of projects with proper tests and noone defining any particular #EqualsAndHashCode, so by default is just comparing the instances, and those projects passed all kind of CRUD tests green, and had no bugs on production
Basically, you'd get some problems when you have bi-directional relationships between entities. For example, if Entity1 has #OneToMany access to Entity2, and Entity2 has #ManyToOne access to EntityId, and both of these entities have #EqualsAndHashcode without specifying fields (i.e., equals and hashcode are generated for all fields including those for relations). In this case, you'd have a circular reference, hence a StackOverflow exception.
In order to avoid that, you can rely only on a field with #Id for constructing equals and hashcode (there are some examples with this approach in hibernate docs). But in this case, you'd get another kind of problems, e.g. if you store transient entities with auto-generated ids in a set (as child entities for some parent one), it wouldn't work correctly because the id field will be null in this case. Probably, you'd need to use some other fields in equals and hashcode in this case.
So, there is no correct answer to this question. You need to make a decision every time you construct your entities.

Best approach for linking diverse entity types in JPA

Short version for the hasty:
There's various tables/entities in my domain model which have the same field (a UUID). There is a table where I need to link rows/instances of such entities to other JPA-managed entities. In other words, the instance of the field in that link table won't be known up-front. The two approaches I can think of are:
Use an abstract entity and a TABLE_PER_CLASS strategy, or
use an #MappedSuperClass store the class name of the instance in the link table as well, or something similar that lets me define logic for getting the actual instance from the right table.
Both have advantages and disadvantages in terms of complexity and performance. Which do you believe to be best, is there maybe a third option, or have you tried something like this in the past and would advice/strongly warn against?
Long version in case you want more background:
I have a database/object model wherein many types have a common field: a universally unique identifier (UUID). The reason for this is that instances of these types can be subject to changes. The changes follow the command model and their data can be encapsulated and itself persisted. Let's call such a change a "mutation". It must be possible to find out which mutations exist in the database for any given entity, and vice-versa, on which entity a stored mutation operates.
Take the following entities with UUIDs as an (extremely simplified) example:
To store the "mutations", we use a table/entity called MutationHolder. To link a mutation to its target entity, there's a MutationEntityLink. The only reason this data isn't directly on the MutationHolder is because there can be direct or indirect links, but that's of little importance here so I left it out:
The question comes down to how I can model the entity field in MutationEntityLink. There are two approaches I can think of.
The first is to make an abstract #Entity annotated class with the UUID field. Customer, Contract and Address would extend it. So it is a TABLE_PER_CLASS strategy. I assume that I could use this as a type for the entity field, although I'm not certain. However, I fear this might have a serious performance penalty since JPA would need to query many tables to find the actual instance.
The second is to simply use #MappedSuperClass and just store the UUID for an entity in the entity field of MutationEntityLink. In order to get the actual entity with that UUID, I'd have to solve it programmatically. Adding an additional column with the class name of the entity, or something else that allows me to identify it or paste it in a JPQL query would do. This requires more work but seems more efficient. I'm not averse to coding some utility classes or doing some reflection/custom annotation work if needed.
My question is which of these approaches seems best? Alternatively, you might have a better suggestion, or notice I'm missing something; for example, maybe there's a way to add a type column even with TABLE_PER_CLASS inheritance to point JPA to the right table? Perhaps you've tried something like this and want to warn me about numerous issues that would arise.
Some additional info:
We create the database schema, so we can add whatever we want.
A single table inheritance strategy isn't an option. The tables must remain distinct. For the same reason, joined inheritance doesn't seem a good fit either.
The JPA provider is Hibernate and using things that are not part of the JPA standard isn't an issue.
If the entities don't have anything in common besides having a uuid I'd use the second approach you describe: use MappedSuperclass. Making the common superclass an entity would prevent you to use a different inheritance strategy if needed, would require a table for that super entity even if no instances exist and from a business point of view it's just wrong.
The link itself could be implemented in multiple ways, e.g. you could subclass MutationEntityLink for each entity to map (e.g. CustomerMutationEntityLink etc.) or do as you described it, i.e. only store the uuid as well as some discriminator/type information and resolve programatically (we're using that approach for something similar btw.).
You need to use #MappedSuperclass while inheriting associations/methods/properties whereas TABLE_PER_CLASS is generally used when you have entity and sub-entities. If there are entities having an association with the base class in the model, then use TABLE_PER_CLASS since the base class behaves like an entity. Otherwise, since the base class would include properties/attributes and methods which are general to such entities not related to each other, using #MappedSuperclass would be a better idea
Example1: You need to set alarms for some different activities like "take medicine", "call mom", "go to doctor" etc. The content of the alarm message does not matter, you will need a reminder. So use TABLE_PER_CLASS since alarm message, which is your base class is like an entity here.
Example2: Assume the base class AbstractDomainObject enables you to create login ID, loginName, creation/modification date for each object where no entity has an association with the base class, you will need to specify the association for the sake of clearing later, like "Company","University" etc. In this situation, using #MappedSuperclass would be better.

About the use of #ForceDiscriminator/#DiscriminatorOptions(force=true)

Why is #ForceDiscriminator or its equivalent #DiscriminatorOptions(force=true) necessary in some cases of inheritance and polymorphic associations? It seems to be the only way to get the job done. Are there any reasons not to use it?
As I'm running over this again and again, I think it might help to clarify:
First, it is true that Hibernate does not require discrimination when using JOINED_TABLE mapping. However, it does require it when using SINGLE_TABLE. Even more importantly, other JPA providers mostly do require it.
What Hibernate actually does when performing a polymorphic JOINED_TABLE query is to create a discriminator named clazz on the fly, using a case-switch that checks for the presence of fields unique for concrete subclasses after outer-joining all tables involved in the inheritance-tree. You can clearly see this when including the "hibernate.show_sql" property in your persistence.xml. In my view this is probably the perfect solution for JOINED_TABLE queries, so the Hibernate folks are right to brag about it.
The matter is somewhat different when performing updates and deletes; here hibernate first queries your root-table for any keys that match the statement's where clause, and creates a virtual pkTable from the result. Then it performs a "DELETE FROM / UPDATE table WHERE pk IN pkTable" for any concrete class withing your inheritance tree; the IN operator causes an O(log(N)) subquery per table entry scanned, but it is likely in-memory, so it's not too bad from a performance perspective.
To answer your specific question, Hibernate simply doesn't see a problem here, and from a certain perspective they are correct. It would be incredibly easy for them to simply honour the #DiscriminatorValue annotations by injecting the discriminator values during entityManager.persist(), even if they do not actually use them. However, not honoring the discriminator column in JOINED_TABLE has the advantage (for Hibernate) to create a mild case of vendor lockin, and it is even defensible by pointing to superior technology.
#ForceDiscriminator or #DiscriminatorOptions(force=true) sure help to mitigate the pain a little, but you have to use them before the first entities are created, or be forced to manually add the missing discriminator values using SQL statements. If you dare to move away from Hibernate it at least costs you some code change to remove these Hibernate specific annotations, creating resistance against the migration. And that is obviously all that Hibernate cares about in this case.
In my experience, vendor lockin is the paradise every market leader's wildest dreams are about, because it is the machiavellian magic wand that protects market share without effort; it is therefore done whenever customers do not fight back and force a price upon the vendor that is higher than the benefits reaped. Who said that an Open Source world would be any different?
p.s, just to avoid any confusion: I am in no way affiliated to any JPA implementor.
p.p.s: What I usually do is ignore the problem until migration time; you can then formulate an SQL UPDATE ... FROM statement using the same case-switch-with-outer-joins trick Hibernate uses to fill in the missing discriminator values. It's actually quite easy once you have understood the basic principle.
Guys let me try to explain about #DiscriminatorOptions(Force=true).
Well , it is used in single table inheritence, i have recently used this in one of the scenario.
i have two entities which was mapped to single table. when i was trying to fetch the record for one entity i was getting list of result containg records from both the entities and this was my problem. To solve this problem i have used #DiscriminatorOptions(Force=true) which will create the predicate using Discriminator column with the specified value mapped to the corresponding entity.
so the query will be look like this after i used #DiscriminatorOptions(Force=true)
select *
from TABLE
where YOUR PREDICATE AND DiscriminatorColumn = DiscriminatorValue
I think this is more of my opinion but I think some will agree with me. I prefer the fact that Hibernate enables you to not use a discriminator. In several cases the discriminator isn't necessary.
For example, I have a Person entity which contains stuff like a name, a date of birth, etc. This entity can be used by several other entities like Employee or Customer. When I don't reference Person from other entities, but reference Employee or Customer instead, the discriminator isn't used as Hibernate is instructed to fetch either one.
#yannisf ForceDiscriminator is not the only solution to solve this issue.
You can do instanceof tests for each child class. Though this will be like hardcoding your classes in your code but is a cleaner way to solve the problem if the discriminator column is not populated.
This also helps your code avoid mixing jpa and hibernate annotations.
As pointed out by yannisf, instanceOf is kind of an antipattern in the OO world.
Another solution could be changing your entity mapping. Suppose an entity A has a refernce to a superclass B and B has child classes of type C1 and C2, the instead of A pointing to B, you can have C1 and C2 have a foreign key pointing to A. It all comes down to changing the entity design so as not to mix annotations.
Thanks
Vaibhav

Best practice: best database naming convention for JPA? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
In Java the naming convention for properties en classes (entities) are done the CamelCase way:
#Entity
public class UserMessage implements Serializable {
#Id
private Integer id;
private String shortTitle;
private String longTitle;
private String htmlMessage;
}
But in the SQL world it’s considered a best practice to use upper case with underscores between words (like Java constants). In the SQL world is also considered a best practice to include the table name in the column names, this way foreign keys are in most cases named exactly the same as the id in the original table.
CREATE TABLE USER_MESSAGE (
USER_MESSAGE_ID MEDIUMINT(8) NOT NULL,
USER_MESSAGE_SHORT_TITLE VARCHAR(20),
USER_MESSAGE_LONG_TITLE VARCHAR(80),
USER_MESSAGE_HTML_MESSAGE TEXT NOT NULL
);
Should I follow both standards and use the name attribute on #Table and #Column? Or should I follow the Java conventions and rely on the default JPA mappings.
What is the most common approach and/or the best approach on this conflict of standards?
Should I follow both standards and use the name attribute on #Table and #Column? Or should I follow the Java conventions and rely on the default JPA mappings.
If the JPA default conventions don't match the preferred conventions of your company (there is no "one true" standard), override them. This can be done using the #Table and #Column annotations (in the particular case of Hibernate, you could also provide your own implementation of a NamingStrategy).
What is the most common approach and/or the best approach on this conflict of standards?
There is no conflict, there are Java naming conventions, there is one default convention on the JPA side for the mapping of objects to tables (because JPA had to pick one) and there is no "one true" standard on the SQL side. So:
if your company doesn't have any SQL naming conventions, you could use the JPA conventions
if you don't like them, override them
if your company has conventions in place, follow them and override the JPA defaults
I suppose that this depends on whose conventions you're referring to. I do not put the table name into the column name - what's the point of losing half your namespace just to repeat what you already know? (Some of) the rules I (try to) follow are:
Long, meaningful names are better than short names, e.g. TRANSACTION_DATE rather than TRAN_DT. Yes, I'm old enough to have written Fortran when you were limited to 6-character variable names, and I recall Basic variants where you only had A-Z, A0-Z0...A9-Z9 - but I'm also old enough to have learned better. Single-character variable names for indices, etc, are fine - and in fact traditional - but when I find a function with twelve single-letter variable names each used for multiple purposes I...am not amused.
Artificial primary keys are named ID_<<"name of table">>.
Single-field natural data primary keys are best. Two-field natural primary keys are OK. Three or more fields - create an artificial primary key and make the natural key an alternate unique key.
Thou shalt never, ever, ever count on a date, time, or date/time field to be unique. Ever. Don't forget this. I mean it.
Obfuscatory coding techniques are equivalent to incompetence.
I'm sure there's more, but it's a start. All IMHO. YMMV.
Share and enjoy.
Follow both. The db convention should be there for DBA sake and manual reports and queries where the mind set is different. Use the name params on annotations to achieve this.
As far as I'm concerned either are acceptable. But if you decide you don't want the default camel case, you CAN get a different naming strategy without resorting to the tedious and error-prone task of adding the name attribute to every annotation.
Take a look at Hibernate's org.hibernate.cfg.ImprovedNamingStrategy class. It uses underscores instead of camel case. It is simply a matter of setting a property on your Hibernate configuration to use it.
You could also extend the ImprovedNamingStrategy to prepend the table name or do all uppercase if you really want, but that seems unnecessary.

What is a good inheritance strategy with Hibernate and JPA?

I have this situation:
I have an entity, Person, that contains all personal details of a person, like birth date, street address, municipality ecc ecc.
And I have an entity ClubMember that describe a member of a club and contains some field like: registration date, type of member, credit, ecc ecc
So, a ClubMember is a Person, and I think is correct describe this with a inheritance:
ClubMember extends Person, but, what type of strategy?
I would obtain two table in database, Person and ClubMember, with ClubMember that contain id_person like an #OneToOne relationship, but keep the inheritance between entities; is this possible (and is correct)?
JOINED is the strategy closest to my target, but I lose the ID field of table ClubMember, in fact ID become the ID of table Person...
Blow, you should keep performance issues when choosing some kind of inheritance strategy. Here you can see a good insight about available inheritance strategies. Do not forget a inheritance can be re-writen as a association as follows
instead of
public class A {}
public class B extends A {}
you can use
public class B {
private A a;
}
Or you can use MapedSuperClass To map all of your inherited properties whitout using any Hibernate/JPA inheritance strategy. See here
Keep in mind when using default JPA/Hibernate annotations, Hibernate always fetch all of subclasses. If you have a single hierarchy, prefer To use Single Table Inheritance strategy. Joined strategy is better designed when you have a complex hierarchy but it suffers due To performance issues when querying for any entity.
EDIT: below answer assumed NHibernate, apologies beforehand if it doesn't apply to Hibernate
This is not always trivial, even it can be trivially implemented (see below), and should be considered thoroughly. In my experience, it's best to stick to good old aggregation, or even just fields, where each ClubMember has-a person, instead of is-a person. This may not entirely feel right, but it works easier with your configurations, the CRUD operations and your abstract DAO classes. Auto-mapping tools often don't support subclassing out of the box.
Also, people that work with both your database and the DAL, will have an understanding for this mapping (i.e., Person as a one-to-one mapping to ClubMember, add non-null to the Person-property and you have your constraint as well), because it resembles the database more closely. You may argue of course that the whole idea of ORM is to remove this similarity ;).
If you want to experiment on this path or if you like to see how it's done and apply it to your situation, Ayende has a nice blog on the subject of NHibernate and inheritance. It's a bit basic, but you'll get the idea. If you use Fluent NHibernate, it becomes a bit easier even, see this brief tutorial.
I would make ClubMemeber extend Person, as you suggested, and use the table per class heriarchy mapping strategy.
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance-tableperclass

Categories