I checked
Hibernate 'Inverse' in mapping file and http://www.nhforge.org/doc/nh/en/#collections-bidirectional and http://blog.xebia.com/2009/03/16/jpa-implementation-patterns-bidirectional-assocations/
Do i always have to use inverse=true for the bidirectional mappings on the set (parent) side?
What are the alternatives? Is it also possible to define both sides not-null and not updateable?
if you have a bidirectional mapping then it causes harm to not have one side inversed because if you have Cascade.All both sides would try to maintain the association meaning duplicate entries in link tables or redundant Updates.
Both sides as not updateable is useful for readonly associations.
Related
I am learning persistence with Hibernate (and JPA) on Udemy and the presenter explains an alternative to the previous associations discussed (unidirectional OneToOne, bidirectional OneToOne, Unidirectional OneToMany, bidirectional OneToMany), called the #JoinTable JPA annotation.
He mentions that sometimes only a small selection of the "Many" entities are associated with a specific kind of "One" entities and that we don't want a field on the "Many" entity to embody the association with the "One" entity since that field will remain null for most instances. He goes on to recommend the #JoinTable for this situation.
My question is, considering the effect of the #JoinTable option on the Java entities, why not just use the Unidirectional #OneToMany annotation on the "One" entity and leave the "Many" entity as-is? Which additional features would #JoinTable bring to the situation from within Java beyond what Unidirectional #OneToMany brings?
Then he is clearly wrong, #JoinTable is definitely not necessary here and will introduce overhead in terms of memory (more data to store) and time complexity (another table to join).
You're right about that you only need #JoinColumn to map one-to-one and one-to-many relationships (and mappedBy on the other side if it should be bidirectional).
P.S.: I would consider going further with this course, as it seems to be flawed even with the very basics of jpa.
I have two tables. Transactions and Errors. There exists a One-To-Many relationship between Transactions and Errors. This is a bi-directional relationship and Errors is the owning side as #JoinColumn is specified in the Errors class. I want to understand what exactly does it mean to "OWN" the relationship. Say at the moment I have,
PROCESSED (column in TRANSACTIONS) set to N
ACTIVE (column in ERRORS) set to 1
Scenario 1:
Now lets suppose we execute the below code.
transactions.setProcessed("Y");
errors.setActive(0);
transactions.setErrors(errors);
entityManager.merge(transactions);
I understand that the PROCESSED field will get set to "Y" in TRANSACTIONS but will the ACTIVE field in ERRORS also get set to 0 or not given that transactions IS NOT the OWNING side of the relationship?
Scenario 2:
On the other hand, if we execute the below:
errors.setActive(0);
transactions.setProcessed("Y");
errors.setTransactions(transactions);
entityManager.merge(errors);
I understand that the ACTIVE filed in ERRORS will be set to 0 but will the PROCESSED field in TRANSACTIONS also be set to "Y" given that ERRORS IS the OWNING side of the relationship?
How do JPA cascade types tie into scenarios like this?
In a non-bidirectional relationship, you define a mapping. When you make a change to that mapping, it is obvious what will happen - a foreign key will get updated. Because there is only one mapping, there can be no conflict (many JPA providers will throw errors if they detect you have more then one writable mapping for a field).
With a bidirectional relationship, this control is less obvious. In your transaction-Error bidirectional relationship, assume it is a OneToOne bidirectional mapping, and Transaction1 is set to point to Error1 and vis versa. Lets say your application determines that Transaction1 should be pointed to Error2 instead, and changes the reference. If Error1's reference to Transaction1 isn't corrected to reflect this situation, there is a problem for JPA in determining what value to put into the foreign key. This is where ownership comes into play. The owning side is considered the writeable mapping, and changes to it control the foreign key fields. In a OneToMany, the owning side is usually the ManyToOne back reference because it is more natural since the foreign key is in the table holding the ManyToOne anyway. If you make a change to add an Error to a Transaction but do not change the Error to also reference that Transaction, your object model will be out of sync with what goes into the database - The foreign key in Error will not be changed, but the transaction object will show an error in its list until it is refreshed or reloaded from the database.
Cascading is something unrelated to ownership. It just means the operation (persist, merge, delete, refresh) applies to the entity referenced by the relationship. If using cascade.all an call em.refresh(transaction), the transaction and all referenced Errors will be refreshed from the database. Any relationships Error then has that have a cascade setting of ALL or REFRESH will also get refreshed and so on. JPA should detected that it has already refreshed the referenced Transaction instance if you place it on the back references, but why risk it. Generally, cascade options should only be placed on mappings where they are required to avoid unintended consequences. If you aren't sure if it is needed, leave it off until you are sure. Things like lazy fetching and other optimizations can cause all sorts of strange and hard to find bugs when someone goes and puts a cascade refresh everywhere.
In your example, you might put a cascade merge on the root entity that your application will be passing around. Any changes made to that graph then are easily picked up with a single merge call without having to call merge on each individual leaf. How your model is built and serialized though will affect the merge, so generally cascade options are put only on the root->Leaf relationships to avoid issues where the root -> leaf -> root' where root != root'. If you have cascade merge on both sides, the state of root' might overwrite your changes in root.
When we say that Errors is the owning side, that means foreign key of the relationship lies within the Errors table(which you are doing via #JoinColumn). Thus, the owning side of the relationship is the one in which reference column of the other entity will be present.
You can define the inverse side of relationship by specifying #OneToMany in the Transactions entity.
Now comes the second part of your question regarding the update of transactions and errors. In my view you can update List associated with a transaction by applying appropriate mode of cascade(persist,delete etc) which means you can specify in your Transaction entity #OneToMany(cascade=CASCADETYPE.MERGE) while specifying the inverse relationship. In this way, if whenever you will update a transaction row, corresponding error rows can also be updated.
However, I don't think it is a good practice to cascade in the other way ie if you update child entity the parent entity should also get updated as it may lead to many data inconsistencies
I want to raise up a question regarding unidirectional and bidirectional associations.
From my point of view it's always better to favor unidirectional associations because bidirectional seems to be excessive and classes wired by bidirectional associations are more cohesive.
How do you think, am I right? To my mind even if bidirectional associations are needed to simplify HQL queries it is better to avoid it thus it can complicate the architecture.
What do you think about it?
You consideration seems concerned only with implementation of the relationship itself.
The most important thing is that these things model relationships existing somewhere, and if the relationship being modeled is truly bidirectional, it will be much easier to program around a model which represents that relationship such.
As an example 2 unidirectional relationships instead of one bidirectional permits for one of these relationships point back at the wrong element:
A --> B --> C
... while B should be pointing back at A:
A <==> B
I would like to now what is the difference between CascadeType and FetchType in Hibernate?
They seem very similar but I guess they are not interchangeable, right?
When to use them? Can they be used both at the same time?
These are 2 different things:
The CascadeType in Hib. could be REFRESH, MERGE, ..., ALL you put it under the related entity and it determines the behavior of the related entity if the current entity is: refreshed, updated, deleted, e.t.c.. So whenever you entity is affected the CascadeType tells if the related entity should be affected as well.
The FetchType could be only of 2: EAGER and LAZY. This one you as well put under the related entity and it determines whether the related entity should be initialized right away when the current entity is initialized (EAGER) or only on demand (LAZY).
Cascading is used for propagating entity state transitions from a Parent entity to a Child.
Fetching is used for loading associated entities and you can have:
global fetch policies (defined through entity mapping)
query-time fetch policy (using the HQL/JPQL FETCH directive)
Both are different configurations, you can relate it with simple SQL.
Cascade tells you what happens when one entity gets updated ( on delete cascade in sql)
Fetch tells how the query is going to be executed ( join, lazy ...)
There's a big difference between the two of them.
CascadeType is a property used to define cascading in arelationship between a parent and a child.
FetchType is a property used to define fetching strategies which are used to optimize the Hibernate generated select statement, so that it
can be as efficient as possible.
You can find more about them in:
Hibernate – fetching strategies examples
Hibernate JPA Cascade Types
Recently, I have been learning about Hibernate, and I am facing some difficulties. My first problem is as follows: I am very much confused with the below terms.
Bidirectional mapping
Many to One
Because, as far as I know, in rdbms we first need to insert in parent table. Then we can insert on child table, so the only possible scenario is one-to-many (first parent then children). Then, how is many-to-one is going to work? Second, what is this bidirectional mapping in regards to Hibernate. Specifically, different types of join annotations confuse me a lot. I am listing those annotations below.
1.#JoinTable(name = "Tbale_Name", joinColumns = { #JoinColumn(name = "Column_Name") },
inverseJoinColumns = { #JoinColumn(name = "Another_ColumnName") })
2.#OneToMany(mappedBy="department")` this mappedby term
3.#PrimaryKeyJoinColumn
Please help me understand these concepts.
The first thing I would say is don't think in terms of tables but think in terms of Objects.
What you are trying to express with the annotations is the relationship between objects, let hibernate work out how to persist the data. You can obviously manually check the SQL but the idea of using an ORM is to map the relationships between entities accordingly and let the ORM figure out the complexity around generating SQL etc.
Its worth noting that the parent -> child relation can be mapped using #ManyToOne by adding mappedBy to the non-owning (child) side of the relationship. Hibernate then will determine which entities to insert into the database first. Running with a TransactionManager will enforce integrity with multi table inserts. Hibernate will also workout which entities need to be persisted, for example if you add an new object on the many side to an existing object on the one side.
Furthermore, its worth understanding that in some cases it won't always be the database that generates the primary key in a parent -> child foreign key. Its possible for the code to generate the Identifier and hibernate will persist them according.
Bidirectional mapping means that object entities have a reference to each other. i.e. You can retrieve the second entity from the first entity. Bidirectional mapping supports one-to-many
or many-to-many. I.e. OneToMany = a Set on one of the entities. Many-To-Many = Sets on both entities.
JoinTable tells hibernate that a table in the database can be used to map to other tables together. See JPA "#JoinTable" annotation for more information. JoinColumn tells hibernate what column to use to make the join between the two entities. Hibernate needs these to construct the SQL.