Have an entity with a OneToMany relationship in Spring Data that I would need to filter by a specific column. I've been unable to find a satisfying solution to get it with a single query (both parent entity and the filtered OneToMany in one go) so I'm now thinking in having it lazy fetched and after getting the parent entity, have a separate query to retrieve the linked entities and just using a setter to link them together (ie: parent.setChildren(childrenRepository.findAllBy...)).
Question is: would this effectively disable any future trigger to the lazy fetch so my manually set children would remain? Use case here is to add these children manually in certain cases, and using the default lazy fetch when the conditions don't apply.
I tested this and seems to be working as intended, but could not find information on when the lazy fetch should be triggered as to make sure my logic would work in any scenario (is it disabled as soon as the setter is invoked? is this documented anywhere?)
Thanks in advance.
Related
I'll simplify the example to get the idea across. My model looks like the following :
Projects have a ManyToMany relationship with Jobs. In order to create the join table, I created a ProjectJob entity that has an added column, "job_order". Project references an OneToMany link to a list of ProjectJob, with CascadeType.ALL.
I have a UniqueConstraint on ProjectJob that looks like this :
#UniqueConstraint(columnNames = {"project_id", "job_order"}
Everything works like a charm unless I want to reorder the jobs in the project. Basically, I flip the orders around in my service and made sure that every ProjectJob was a unique job_order in the list, and then save the Project (since the ProjectJobs will be cascaded). Problems arise when JPA/Hibernate tries to flush the transaction since it tries to update "row by row", and obviously the UniqueConstraint is violated after the first update (even though the whole batch of updates would give a coherent state).
Weirdly enough, the service call happens inside a transaction, so I'm not sure why I get this error.
Is there any way to update the child members of a collection in a unique statement so that the UniqueConstraint gets checked after all the children have been updated, instead of getting triggered after the first one? If not, what solution is available for my use case?
You could try to use deferred constraints. Or you use #ManyToMany #OrderColumn List<Job> jobs in Project instead which handles all of this automatically for you.
I have an entity "Event" that has a ManyToOne relationship with the entity "Organization". So an Organization can have multiple events.
What I originally wanted to do was to filter the entity Event using a property of the Organization entity. So basically when I fetch events, only return the events that have an Organization.code= :codeParam.
To accomplish that I implemented a hibernate filter with :
#FilterDef(name="codeFilter", parameters=#ParamDef( name="codeParam", type="string" ) )
...
#ManyToOne
#JoinColumn(name="Organization_Id")
#Filter(name="codeFilter", condition=" code = :codeParam")
private Organization organization;
...
Filter hibernateFilter = sess.enableFilter("codeFilter");
hibernateFilter.setParameter("codeParam", "hola");
Unfortunately according to a post from the Hibernate Team on the hibernate forums, this is not possible :
A Hibernate data filter does not change the multiplicity of an association. By definition it therefore does not filter many-to-one, one-to-one, or any load() or get() operation.
What is it supposed to do, return NULL instead of an instance? NULL does not mean FILTERED, it means NULL. You guys are using filters wrong.
So my question is : is there any way to filter the base entity ("Event") with a condition on the entity from a manyToOne relationship (Organization.code= :codeParam)?
I need this to be enforced every time there is a fetch of events, so a solution using the already existing hibernate filters or something similar would be greatly appreciated.
EDIT1: The question is a simple example of what needs to be done on a significantly bigger scale. Basically, we want to add security to all our Entities and their own nested Entities through the use of a globally defined filter on a Unix permissions row that all our tables have.
WARNING: Do not do this, it is dependent on Hibernate internals and prone to breaking on schema changes, and possibly on variations in individual query setup.
Set Hibernate to show its generated sql, run the query you want to filter (in this case, loading some Event objects), and check what name it assigns to the join used for fetching the related Organization. For example, the generated sql might include inner join Organization someNameHere on this_.Organization_Id = someNameHere.OrganizationId. Then apply the filter, not to the association, but to the Event class, with condition "someNameHere.code = :codeParam".
This is, unfortunately, the only way I've been able to find to filter one class by the properties of an associated class.
I'm trying to make a more robust solution, but it's a complex issue and I'm still in the research stage for that. I expect it will use code generation (through an annotation processor) and programmatic modification of Hibernate's mapping information on startup, but I'm not sure what else yet.
I would like to keep the Parent/Child relationship but when I parse through the Parent Object I don't want to fetch the child elements.
Proxies are generated so that Hibernate can intercept calls to uninitialized associations and try fetching them on-demand.
The LazyInitializationException is a code smell. You get it because you haven't properly initialized all the required entity associations prior to closing a Session. Switching to EAGER associations is also a bad idea because the fetching policy is a query responsibility.
Try to reduce the number of associations if you don't need them and use queries instead. You can build an application with just many-to-one associations (mirroring the FK relations) and instead of one-to-many associations you can have DAO methods.
As for this statement:
I would like to keep the Parent/Child relationship but when I parse
through the Parent Object I don't want to fetch the child elements.
If you keep the Parent/Child relationship you always need to load the association prior to using it. Trying to remove the proxies sounds like you are trying to hack a solution instead of properly design your application layers.
So Proxies are fine and they allow you to improve the application performance, because you don't always fetch all associations when you try to access a root entity.
To disable proxies you just have to annotate your entities with the Proxy annotation:
#Proxy(lazy=false)
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
I have one to many association in my dto,
Parent DTO : Question
Child DTO : History
Question 1:
Means One question record has many history records, I am using JPA2.x with hibernate,
I bound the entities with lazy fetching method/mode. some places I want the lazy fetching...
and some places I don't want the lazy fetching not even egar. Means I don't want the data collection itself. I need only the parent class list, even if I call getHistories() method, it should not do lazy fetch in few places.... How to use entityManager to avoid lazy fetching.....even though the collection was set to lazy fetch mode.....?
Question 2:
I need to encrypt the question using mysql encode/decode functions. when inserting encrypt the value and save. when selecting decode the content.....
Solution can be in mapping or criteria query...?
Thanks In Advance....!
Question 1:
Your requirement makes no sense. If you don't want to access the history, don't call getHistories(). If you access the collection of History, either your Question is attached, and the collection will be loaded, or it's detached, and you'll get a lazy loading exception.
Question 2:
See http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/annotations/ColumnTransformer.html. The example in the javadoc is precisely what you want to do.
For question 1, you need to do two things,
If you want your parent-child entities to be selected 'lazily', then annotate the bir-directional fields with fetch = lazy. This should work well in the hibernate session, as long as you dont load or 'touch' one of the lazy loaded fields.
If you want your parent-child entities to be selected 'eagerly', then anotate the fields in the bi-directional association as fetch = eager.
If you want 'some places I don't want the lazy fetching not even egar', then you have to decide at code time, whether to have a relationship between the parent-child entity, if you don't, then just dont map the bi-directional association. You CAN create more than one entity class to map different assoications, even entities with no association.