I have an entity Application.java, which in turn has a property
#Audit(changeTracker = AttributeValueListChangeTracker.class)
#OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true, targetEntity = AttributeValue.class)
#OrderBy
#JoinColumn(name = "application_id")
#LazyCollection(LazyCollectionOption.FALSE)
private List<AttributeValue> attributeValueList = new ArrayList<AttributeValue>();
This eager fetching of this property is posing a problem in performance. I cannot make it lazy as in some cases eager fetch is required.
The case on which I am working doesn't require eager fetch.
is there a way to make this property load lazy just for my case?
You can write custom fetch method either via HQL or let's say Spring Data JPA which would not blindly go for whole entity (and it's eager relationships) but for certain properties which your case requires...
Related
On a bidirectional relationship beetwen two entities (a ControlTable made up of ControlSteps), i'm simply trying by different ways to request a ControlTable by knowing the collection ControlSteps of it. I know that it's not recommended to have this bidirectionnal mapping but i need to know each childs of a parent, and the parent for each child.
I configured it like this in ControlTable class:
#OneToMany(mappedBy = "controlTable",cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Fetch(FetchMode.JOIN)
private Set<ControlStep> controlSteps;
And like this for ControlStep class :
#ManyToOne(optional=false, fetch=FetchType.LAZY)
#JoinColumn(name="ctrl_table_id", referencedColumnName = "id")
private ControlTable controlTable;
When i use the default JPA query findAll(), it's not working to get the list of ControlTables (or only one) because it's requesting recursively the parent in the child's parent (infinite response).
In another way, itried to put all in LAZY loading, with an HQL query fetching the childs, but the result is the same.
Do you have any idea of how to get these collections without problems?
Thank you very much by advance
Found it. The problem was Spring Data Rest and JSON transformation, for more details :
Infinite Recursion with Jackson JSON and Hibernate JPA issue
I have a class Usuario. User have association with UsuarioPerfil:
public class Usuario{
/*Attributes*/
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "id_usuario_perfil", referencedColumnName = "id", foreignKey = #ForeignKey(name = "fk_usuario_id_usuario_perfil"))
#Getter
#Setter
private UsuarioPerfil usuarioPerfil;
}
public class UsuarioPerfil{
/*Attributes*/
}
I am performing queries using the Criteria, as follows:
Session sessao = this.getEntityManager().unwrap(Session.class);
sessao.createCriteria(Usuario.class).list();
However, in some cases wish list does not come in the data UsuarioPerfil entity, only the User. How can I accomplish this using Hibernate Criteria?
Note: I know this is possible using Hibernate or JPA Query
I don't believe you can explicitly do what you are asking with the Hibernate Criteria API because it is generally accepted practice to make associations LAZY and set them to EAGER on a case-by-case basis.
Therefore, change your mapping to use fetch = FetchType.LAZY and then in the cases where you need the association in your query, specify it as:
criteria.setFetchMode("usuarioPerfil", FetchMode.JOIN);
If you have access to JPA's EntityGraph annotations, I would strongly suggest you look into those as well. At a minimum, you can at least look at Hibernate's FetchProfile concept because those go along way to defining fetch strategies by name which helps keep code and queries much cleaner.
I have two entities connected with a bidirectional OneToMany/ManyToOne relationship.
#Entity
class One {
#OneToMany(mappedBy = "one", orphanRemoval = true, fetch = FetchType.EAGER)
private Set<Many> manies;
// ...
}
#Entity
class Many {
#ManyToOne
#JoinColumn(name = "one_id", nullable = false)
private One one;
// ...
}
When I want to remove a Many instance, I remove it from its One's manies Set and delete it from the database. If I take the same One instance and save it again (because I changed anything, it doesn't have to be related to the relationship), I get an exception:
javax.persistence.EntityNotFoundException: Unable to find test.Many with id 12345
The ID (in this example 12345) is the ID of the just removed entity. Note that removal of the entity 12345 succeeded: The transaction commits successfully and the row is removed from the database.
Adding and removing instances is done with Spring Data repositories. Removing looks more or less like this:
one.getManies().remove(manyToRemove);
oneDao.save(one);
manyDao.delete(manyToRemove);
I debugged a little and found out that the Set is a Hibernate PersistentSet which contains a field storedSnapshot. This in turn is another Set that still references the removed entity. I have no idea why this reference is not removed from the snapshot but I suspect this is the problem: I think Hibernate tries to remove the entity a second time because it's in the snapshot but not in the actual collection. I searched for quite a while but I didn't encounter others with a similar problem.
I use Hibernate 4.2.2 and Spring Data 1.6.0.
Am I doing something inherently wrong? How can I fix this?
I'm having the same problem.
A workaround is to replace the entire collection.
Set<Many> maniesBkp = one.getManies(); // Instance of PersistentSet
maniesBkp.remove(manyToRemove);
Set<Many> manies = new HashSet<Many>();
manies.addAll(maniesBkp);
one.setManies(manies);
...
manyDao.delete(manyToRemove);
...
oneDao.save(one);
As your #OneToMany relation has orphanRemoval = true, you don't have to explicitly remove the child element from the database - just remove it from the collection and save the parent element.
Try add CascadeType.REMOVE and orphanRemoval
#OneToMany(mappedBy = "one", orphanRemoval = true, fetch = FetchType.EAGER, cascade = CascadeType.REMOVE, orphanRemoval = true)
Than perform delete following
one.getManies().remove(manyToRemove);
oneDao.save(one);
Edited:
I have created POC, look on the UserRepositoryIntegrationTest.departmentTestCase (code)
I am trying to retrieve entities using eclipselink JPA and am looking for a way to reduce the number of queries run to retrieve a single entity. I believe I should be using the #JoinFetch annotation to retrieve sub-entities in the same query as the main entity. This works fine for a single level of join, but not for multiple levels.
In the example below, EntityA contains a collection of EntityB which contains an EntityC. When I retrieve EntityA, I want a single query to return all 3 sets of entity data. In reality it generates 2 queries, 1 joining EntityA and EntityB and then a separate query joining EntityB and EntityC.
Is it possible to combine this into one query?
class EntityA {
#OneToMany(mappedBy = "entityALink", fetch = FetchType.EAGER)
#JoinFetch
private Collection<EntityB> entityBs;
}
class EntityB {
#JoinColumn(name = "X", referencedColumnName = "Y")
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private EntityA entityALink;
#JoinColumn(name = "A", referencedColumnName = "B")
#ManyToOne(optional = false, fetch = FetchType.EAGER)
#JoinFetch
private EntityC entityCLink;
}
class EntityC {
#Id
#Basic(optional = false)
#Column(name = "SomeColumn")
private String someField
}
If you need reduce number of queries, you may using lazy initialization - FetchType.LAZY instead of FetchType.EAGER - in this way jpa get data from databases when need. But you must remember, this is not working when entity is disconnected from manager. So if you send this entity to other servers in serialize the form (ex. in multi-level application) you must again connected this entity with manager. If you application runs in one server, then you don't have this problem.
Summing up is not the exact answer to your question, but maybe helpful for optimize this code.
Exact answer for you question:
You may using named queries, but then query is parse to sql native query, and you don't sure that this working as you want. But maybe you may using native query method?
em.createNativeQuery("SELECT ... your queries")
For this purpose, please read about using #SqlResultSetMapping annotation to configure result entity class...
First write a query to get EntityA.
EntityA entity = <your Query> ;
then call
Collection<EntityB> entityB = entity.getEntityBs();
for(EntityB eachB : entityB){
EntityC entityCLink = eachB.getEntityCLink();
}
Note: Create setter & getters in each entity.
I have an AbstractEntity class as superclass for all my entites that defines an optimistic lock column like this:
#Version
private long lockVersion;
Now I often get OptimisticLockingExceptions on entities, that are only changed in one the mappedBy relations similar to the following:
#OneToMany(mappedBy = Property.PROPERTY_DESCRIPTOR, cascade = { CascadeType.REMOVE })
private Set<Property> properties = new HashSet<Property>();
Is it possible to exclude those collections from Hibernate optimistic locking? The entity is not changed in the database at all... only others referencing it.
You can exclude a particular property (and / or collection) from increasing the version number if it's dirty by explicitly excluding it via #OptimisticLock annotation:
#OptimisticLock(excluded=true)
#OneToMany(mappedBy = Property.PROPERTY_DESCRIPTOR, cascade = { CascadeType.REMOVE })
private Set<Property> properties = new HashSet<Property>();
Be aware that it's a Hibernate extension to JPA standard.
i think the accepted answer in this question should help you:link
I havn't tried it myself though, but it could be possible to detect changes not requiring version update and not increment the version.