I have two entities Library and Books which are associated by Hibernate #OneToMany in a spring boot project. Fetching books in a particular library through the getter functions renders a LazyInitialisationException. The solution that I could find was making a query in the Books entity and fetching all the books corresponding to the library-id of the library. So, I was thinking why is oneToMany relationship required if we can just store a key corresponding to library in the Books table.
Simply storing a key doesn't provide any consistency assurances. Also, using defined OneToMany or ManyToOne you can also define the cascade types (you would only need to save the parent entity and then all the children would automatically be saved, in a single transaction).
The quick way to fix your problem would be to use FetchType EAGER, but I would recommend fixing whatever you have misconfigured.
Related
AHere's the setup:
Springboot, springboot-data-jpa, hibernate.
I have one entity, a Review, that has a property that has a many-to-one relationship with another entity, a vehicle. The vehicle entity conversely has a one-to-many relationship with the review entity.
To create the review entity via a POST endpoint, I give the vehicle entity as of the properties in the JSON.
This works fine, not only is the review record added in the database but it goes ahead and creates the vehicle entity as well. The only issue is that in the case where the vehicle already exists, instead of making that connection, it creates another record with the exact same information so I have a duplicate vehicle entity.
Is this because I should be handling the creation of the vehicle entity on my own instead of relying on hibernate? Am I just missing some annotation I'm not aware of?
Originally I was getting an error about flushing or something so I added the Cascade.ALL annotation to the review class 'vehicle' property and that fixed that problem. I tried changing the Cascade type as it seems to be relevant somehow but it either breaks the server or doesn't work at all.
My question is would Spring JPA throw exceptions for every query?
I mean, let say there are tables without any relation (FK) between them in database. It is bad design but you cannot change it and it is not up to you.
But you know that data itself should be as there are relations.
That's why you create Entity model with all relations like they are there.
But as I said there is no real relations in database.
And in one point data are inconsistent in database.
Would Spring JPA throw exceptions if there are inconsistency or it will just return you inconsistent data?
I assume with "relations" you mean "foreign keys".
JPA doesn't care about foreign keys.
All it cares about is if the data matches the mapping information on the entities.
So if you have an entity A that references an entity B with id b but such a B does not exist you might eventually get an exception.
Or you might just get an A with a null reference to B.
If the reference is marked as mandatory you might actually not be able to load the A in the first place, because a join is used and therefore not returning any data at all.
Side note: All this depends more on the JPA implementation you are using than on Spring Data JPA.
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.
Thus far I have referred to this repo as a reference for how to structure my repositories in my Spring project which leverages QueryDSL.
The only "shortcoming" of this example for me is that it does not outline how I might write a Repository which uses a chain of more than one OneToMany relationships. Using this repository as an example/reference, they have a "Customer" repository and for each Customer there are many "Address". I'm unsure how I would use give or take the same patterns they are using, but for a Class which had a OneToMany relationship with Customers. Meaning, how would I handle a Repository for "CustomerGroup" which has a OneToMany relationship with "Customers" which in turn has a one to many relationship with "Addresses".
Some patterns have occurred to me, but not seem elegant/optimal so I'm looking for anyone with experience or insight as to what might be a nice way of solving this problem.
I very much appreciate any help!
Do you mean in order to write WHERE statements based on the relations?
For example if you want to retrieve all customer groups that contain a customer from a specific country, you can simply call
QCustomerGroup.customerGroup.customer.any().addresses.any().country.eq("Germany")
To make this working to need to add
#OneToMany
private Address addresses;
to the Customer entity.
When usually fetching an entity from database with doctrine, you get all the related entities as actual classes, which causes a huge JOIN query, if you have lots of relations.
But sometimes I just want to get the actual object, not all the associated entities, just their IDs.
Is it possible to tell doctrine to just fetch the main entity and leave alone the relations?
Update: Sorry, missed the version: I'm using Doctrine 1.2 on a old project.
By default Doctrine use "lazy-loading": it will not retrieve the associated entities if you do not try to access them.
If you just use the ID of the main entity, it will never retrieves the associated entities.
If you want it to be even more lazy, try using the EXTRA_LAZY param.