Netbeans/JPA change owning side of many to many relationship - java

I'm using netbeans "Entity classes from database" function to generate my entity classes. Sadly, netbeans chooses the wrong manytomany relationship owner. I have for example a user and group table which are related via many to many. In my case the group entity is the owner with #JoinTable and User has the "MappedBy" annotation. How can I make User to the owning entity. I could change it manually but after generating it again from database, it will be overwritten. This is really annoying. Any ideas?
Regards, Manu

Related

Spring Data JPA Relationships

here I'am, trying to get a better understanding of JPA Relationships in SpringBoot.
Those Entities has been created following some XML configuration files.
I'm not used to XML and I'm trying to improve my Java/SpringBoot #Annotation skills.
I'll show you 3 Entities with a OneToOne & ManyToOne annotations.
Questions
In Driver -< ServiceRequestDriverVehicle (#OneToMany) the mappedBy="driverId" references the current Driver id field or the JoinColumn(name="driverId") from the other Entity? e.g.: In Vehicle Entity mappedBy use vehicle, which if comes from ServiceRequestDriverVehicle it's named as vehicleId #JoinColumn(name="vehicleId") but it's field name is vehicle, so why where is using vehicle instead of vehicleId as in the Driver case does? Again this is abstracted from an XML configuration that can be wrong.
Are the arrows from the images pointing the right meaning of the Annotation? I mean, is the annotation taking the entity/class of the annotated field to make the relationship mapping?
In the #OneToOne relationship(Driver), is the referencedColumnName="ID" mandatory/necessary or OneToOne is automatically linked to the PK (id)
I have a MySQL model where the Set fields do not appear, should I Annotate those as #Transient or the LAZY fetch is enough?
Thank you for your answers, I hope this can solve future misunderstandings

What is the significance of being the realtionship owner and how does CASCADE work with the two sides in 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

JHipster relation between predefined table USER and my own table

I need to define new table related to predefined 'User' table.
Please, help me to write a correct JDL code for this
entity diagram
I tried to write file "mytable.jh" and import :>jhipster import-jdl mytable.jh
entity MyTable{
userid Long, //relation to table jhi_user
}
relationship OneToMany {
User{id} to Mytable{userid}
}
and got
{ name: 'IllegalAssociationException',
message: 'Relationships from User entity is not supported in the declaration between User and Mytable.',
prototype:
Error
Basically you can't add new fields to the jhi_user table, and JDL won't let you do anything that would cause that to happen.
You can add a User object reference to another entity with something like
relationship ManyToOne {
Mytable{userid} to User
}
Note there that I am not putting {anything} after User -- this means the User has no idea which Mytable it's associated with. If you want to "back up" from an instance of Mytable to an instance of User, you have to search from the Mytable side; the User won't have any fields or getters/setters related to an instance of Mytable.
Also note that the userid field is not necessarily strictly for relating the two entities. The JDL and code generation actually takes care of creating the relationships and primary/foreign keys for you. So
entity Car {
}
relationship ManyToOne {
Car{user} to User
}
means for every User, there are many Cars, or another way of saying it is for every Car there is one user whose field name within the Car object will be user. So you'll have Car.getUser() method, etc.
When you define a field within an entity block, you're defining a property of that entity, not a relation -- that property is independent of all other objects in your model.
You still won't have a User.getCars() method though. This is not possible with current jHipster design.
I think this tip in the jhipster doc might help you, I never looked at it, but a mate did this during my project I'm crrently working on. Hope this helps. You can always ask Paul-Etienne for further information, he will gladly help.

Hibernate Annotations, Create 3rd entity from existing two entities without annotating the already annotated table

I have two tables named USER and ROLE with entities as USER and ROLE resply.
Now I want to create one more entity by using these above entity so that I can fetch datas of both tables.
One more table is there named USER_ROLE which contain two fields "user_id" and "role_id".
I have to accomplish these thing using hibernate annotations.
I tried by creating third entity with annotated table as USER table and properties are some USER table fields and Collection set of ROLE table. But here's the mistake is I annotated the third entity with USER table which is already annotated with User entity.
So now I have to make that third entity without annotating any table, has to access the two entities which are already accessing the table .
how can i accomplish these using hibernate annotations.
kindly help me on this issue
thanks, rajNaveen
As far as I understand what are you looking for can be found in this tutorial.
Just see how #JoinTable is used.
Hope that helps !!!

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