JPA: Remove Child Entities - spring

I have an entity(ex: Document) that is used as child in 4 other entities(using #OneToMany with #JoinTable in parents). I am not using Bidirectional Mapping. My requirement is to remove the Child(i.e Document), and I have two ways to do that, one way is, get the 4 parents, remove child from them and update them. Second, using native query(using jdbcTemplate) to remove entry from 4 join tables and remove the child.
Is there any other way it can be done in much simpler manner?

Create an abstract base class containing the Document as member and user JPA inhertiance --> http://en.wikibooks.org/wiki/Java_Persistence/Inheritance
Than it should be possible to get all users of a document with just one query.
Than it should be relatively easy to remove all references.
Don't do magic behind automatic deletion stuff. Thats for the cost of documentation.

Add orphan deletion (ie. delete child object when it's removed from collection in the parent). To enable it, you need to add
#OneToMany(orphanRemoval=true)
in owning entity.

Related

Do I need to save both entities when adding a oneToMany relationship?

TL;DR: Is it enough to call repository.save() on the owning entity to persist the relationship or do I need to save both entities?
Let's say I have two entities, A and B and a oneToMany relationship between them. A can have multiple B's, B can have an A. B is the owning side of the relationship (has the foreign key). If I have two, already persisted entities and want to add and persist a relationship between them, then I typically do this:
a.addB(b);
b.setA(a);
bRepository.save(b);
My question is, do I also need to call aRepository.save(a)? Thanks in advance, Googling didn't help me to find the answer.
If as you describe the relationship is owned by B, A didn't change at all as far as JPA is concerned. So it doesn't need to get persisted.
If you have persisted or loaded A and B in the current session, no save at all is technically necessary. JPA keeps track of the entities, note that they are changed and will flush the changes to the database at the end of the transaction.
Good question and assuming that you have already saved the A entity the answer should be that you do NOT need to save the parent A entity again since you have added the child entity B to A's list of children yourself and A is already persisted.
If you ever reload A and all its children you should get the same list as you currently have.
Since it is lazy loaded your query should specifically load the children in the case you want that otherwise you might get into the situation where you assume that A has all its children but you doesn't if you reloaded A from the database without getting them.
In general though I have to question why you are keeping A around in the first place. Caching can be a good thing but your cache should refresh A when its children are updated and should fetch all of A's children if that is what is needed. In that case you don't need to add the new child to A yourself b/c it will be overwritten anyway. Probably doesn't hurt, but why do you want to second guess the cache?
More generally the pattern is simply to save B and be done with it. If your code needs A and all its children it should fetch from the database when needed.
These thoughts do not include JPAs entity cache since I have not attempted to get into very specific detail about that.

Panache: Insert or ignore child

I want to persist an entity that has a #OneToMany relationship to a child entity. I'm using Quarkus 1.13.1 with Quarkus Panache.
Example
public class User {
private List<Item> items;
#OneToMany(cascade = CascadeType.ALL)
public List<Item> getItems()...
}
If I want to persist a user (user.persist()) with a few items that already exist in the item table, then I get of course a "duplicate key" exception. So far so good.
But I was wondering if there is a descent way to skip/ignore an insert if an item already exists in the table items.
Of course, I could query the database to check if the child value exists, but this seems somehow tedious and bloats the code with data checks, so I was wondering if there was some annotation or other shortcut to handle this.
A persist operation should be used exclusively to create (store) new objects in the database, and makes the Java objects managed by Hibernate until the Session is closed.
It's really important that you know which objects are managed, and which are not, and distinguish wich ones are newly made persistent rather than just represent an existing object in the database.
To this end, it would indeed be better to load the existing Items first; if you know for sure which ones are already existing in the DB you can use a lazy proxy to represent them and put those in the list before persisting the User.
If you don't know which Items already exist in the database, then you should indeed have to query the database first. There is no shortcut for this operation; I guess we could explore some improvements but generally automating such things is tricky.
I would suggest implement the checks explicitly so you have full control over the strategy. It might be a good idea to make Item a cached entity so you can implement safe validations without performance drawbacks.

Is it allowed to change entities' relationship state in Hibernate Interceptor?

I have an entity that has a Set of child entities. Can I add/remove some of the children in the collection in Hibernate's org.hibernate.Interceptor.onFlushDirty()?
The documentation (javadoc, JBoss userguide) doesn't explicitly mention changing relationship state, so I just want to make sure it's legitimate.
Update
Decided to describe by problem.
There's a Parent entity that has a Set of Child entities. The Child entities are created based purely on fields of the Parent entity, no additional information needed. The children need to be updated each time before persisting the Parent.
I wanted to do it in Interceptor.onFlushDirty() by clearing existing children and adding new reclaculated (i.e. Transient) children, but I'm getting the TransientObjectException. As I understand, it's because I add transient Child entities during flush, but I'm not sure.

Querying multiple tables using jpa repository

Suppose if I have 3 entities - User, Skills, Department
and I have repositories corresponding to all of them - UserRepository, SkillRepository, DepartmentRepository.
I understand that the relation mapping between entities i.e. one-one many-many should be specified in the respective entity classes. The question is I want to use all of the 3 entities in a query. How would I do it? A single repository is associated with only one entity right? So, how/where would I write it?
As there are many different ways to specify queries with Spring Data JPA there are various answers to this.
Maybe you don't have to. If entity A references B and you just want to get the Bs with your A you simply use your ARepository to load As and use object navigation to get your Bs. You might read up on eager and lazy loading for more information about how to control this.
If you want referenced entities in the where condition you can use property paths in your query method names: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
If you are using #Query annotations you can do (almost) whatever you want with JPQL. Among others, you may as well navigate properties to use them in where clauses.
In general, you'd put that query in the matching repository based on the primary entity returned.

A Simple approach to implementing a multi level library with only one parent node, especially with MVC3/EF

I am trying to implement a multi level library. There are only single parent nodes:
Parent1
- Child1
- Child2
Parent2
- Child1
- Child2
I started by implementing this using a link table
LibraryItem -< LibraryItemLink (FkParentId)
-< LibraryItemLink (FkChildId)
Which is fine, and powerful since it allows for multiparent nodes as well as multichild nodes. However I have got into difficulties when trying to delete parent library items. Ideally one should put a "Cascade Delete" on both of the constraints to cover parent or child node deletion, but SQL Server does not like this as it think cyclic deletion may happen. So I wondered whether I was making life to tricky for myself and instead should use a self referencing association to LibraryItem.
LibraryItem -< LibraryItem(Children)
Would this be easier to implement, especially from a CRUD perspective within the MVC3/EF5 world?
The final option is 2 table for 2 levels which is much easier, but more limited.
Thoughts much appreciated.
I would go with a PARENT_ID column in the LibraryItem table, allowing for NULLS and a FK back to the PK of the same table.
For your cascading delete issue, I would use a INSTEAD OF DELETE trigger on that table that;
Deletes all reocrds where the PARENT_ID is the PK of the row being deleted
Then delete the record of the parent itself.

Resources