I want to access the list of organisations from a user object within the main.gsp:
<g:select name="effectiveOrganisation"
from="${session.user.organisations}" optionKey="id" optionValue="name"
value="${session.effectiveOrganisation?.id}" />
The user object is defined by the following class:
class SystemUser {
static hasMany = [organisations: Organisation]
static belongsTo = [Organisation]
static mapping = {
organisations lazy: false
}
}
But when I execute my code, I get:
Exception Message: could not initialize proxy - no Session
Caused by: Error executing tag <g:form>:
Error executing tag <g:select>: could not initialize proxy - no Session
Why does the eager not work here?
It's not clear from your code, but I'm going to assume that you have a many-to-many here based on the belongsTo property.
I've managed to reproduce this with Grails 1.3.5. The problem only seems to affect the side of the relationship that has the belongsTo property. If you tried the same code with organization -> users instead, it would work.
The fix is rather odd: make the users collection on Organization non-lazy too.
This one will have to make it into the GORM Gotchas series!
Related
I have a class of User that has a list (collection) of Projects:
#OneToMany(mappedBy = "user_owner_id")
private Collection<Project> project = new ArrayList<>();
And at some point, I want to see the list of projects and I fetch them:
Session sessionF = sessionFactory.openSession();
sessionF.beginTransaction();
user = sessionF.get(User.class, user.getId());
sessionF.getTransaction().commit();
List<Project> projects = (List<Project>) user.getProject();
sessionF.close();
If I don't do something with projects it throws the error: org.hibernate.LazyInitializationException: could not initialize proxy – no Session
But if I am adding a int projectCount = projects.size(); it works just fine. Why does that happen and how can I resolve it without playing with projects here?
P.S. After I am closing the session I am just passing it through the HttpServletRequest and then going with a for loop over it in a jsp file.
Check Fetching Strategies section of Hibernate Reference Documentation
Lazy collection fetching - a collection is fetched when the application invokes an operation upon that collection. (This is the default for collections.)
Returning your collection from an entity and assigning it to a variable does not involve calling a method on that collection.
I am learning Spring, Hibernate and Thymeleaf. Thymeleaf collections works with Lists and Sets but certain relationships in Hibernate seem are better managed with Sets. This creates a issue when posting list data back to the server that is indexed like workgroup.people[0] etc
So if a Hibernate entity uses something like:
#Entity
public class Workgroup {
#OneToMany(mappedBy = "workgroup", fetch = FetchType.EAGER)
private Set<People> people = new HashSet<>();
...
}
The question how do I get this into a useable entity in Thymeleaf?
Currently if I try to persist (POST) this workgroup entity with some people the form data that is sent back to server looks like:
workgroup.people[0].dueDate:18/09/2017
workgroup.people[0].status:New
workgroup.people[0].peopleText:abc123
workgroup.people[1].supervisor.id:3
workgroup.people[1].assignee.id:3
workgroup.people[1].dueDate:18/09/2017
workgroup.people[1].status:New
workgroup.people[1].peopleText:def456
workgroup.people[2].supervisor.id:4
workgroup.people[2].assignee.id:4
workgroup.people[2].dueDate:18/09/2017
workgroup.people[2].status:New
workgroup.people[2].peopleText:ghi789
And the controller:
#PostMapping("/peopleSubmit")
public String submitPlan(#Valid #ModelAttribute WorkgroupPeople workgroupPeople, BindingResult bindingResult) {
workgroupService.updateWorkgroupPeople(workgroupPeople);
return "redirect:dashboard";
}
Note I have a breakpoint on the controllers first line, but it never gets there before the exception is thrown.
Invalid property 'workgroup.people[0]' of bean class [com.exa.dto.WP]: Illegal attempt to get property 'people' threw exception; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'workgroup.people[0]' of bean class [com.exa.dto.WP]: Cannot get element with index 0 from Set of size 0, accessed using property path 'people[0]'
Do I need to load the workgroup and people into a WorkgroupPeopleDTO object which stores People as a List? & then manage the relationship?
And why do people who use Hibernate seem to prefer sets (I understand the differences to list)
A concrete example would be great. Thanks.
i am trying to solve an issue from work that consists in a method that is called several times in production and breaks, here is the interface's method:
#Cacheable("CategoryDao.findAllLocale")
Set<Category> findAllLocale(String locale);
And here is the implementation:
public Set<Category> findAllLocale(final String locale) {
final Set<Category> localeCategories = this.findAllLocaleRootCategories(locale);
for (final Category rootCategory : localeCategories) {
final Set<Category> localeChildCategories = this.findAllLocaleByParent(locale, rootCategory.getCatId());
rootCategory.setCategories(localeChildCategories);
}
return localeCategories;
}
Is a simple DAO method but the problem is that returns a lot of data and in server productions throws this exception:
01-01-15 10:09:47:984 - {ERROR} categories.GetAllCategoriesAction - User:5007660771072025 - Unexpected exception executing the action
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.company.app.data.Category.categories, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
I think that the exception is something about that the #Cacheable overloads, because the app runs a few hours and works fine but then crash and log that fragment, I want make a "massive" use of this test so i will know is that or something else, any suggestions?
PD: #Cacheable is from ehcache framework
PD2: Sorry for my english
The issue comes from the fact that let Hibernate/JPA entities escape, making them live longer than the session they were attached to.
So the issue comes at a later point when you use one of them (from the cache but it may not even be directly related) and try to access a lazy loaded collection. And that last point fails because you are already outside of the bounds of your Hibernate/JPA session.
As a rule of thumb, you should not cache Hibernate/JPA entities.
I have CustomerEntity mapped to table customers in database. It has one-to-many relations to orders and addresses. Now I retreive customer with orders with next code:
DetachedCriteria criteria = DetachedCriteria.forClass(CustomerEntity.class);
criteria.add(Restrictions.eq("id", patientId));
criteria.createCriteria("orders", CriteriaSpecification.LEFT_JOIN).add(Restrictions.and(
Restrictions.isNull("deletedDate"),
Restrictions.or(Restrictions.isNull("old"), Restrictions.eq("old", BoolType.FALSE))));
CustomerEntity customer = queryDao.searchSingle(criteria);
QueryDAO:
public <T> T searchSingle(DetachedCriteria criteria) {
return (T) criteria.getExecutableCriteria(getCurrentSession()).uniqueResult();
}
But when I try to invoke customer.getAddresses() next exception is thrown:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: , no session or session was closed
It happens because by default hibernate isn't loaded one-to-many entities.
How can I without modifying Customer entity retreive his addresses too?
This exception occurs when you try to access the lazy-loading collection or field at the moment when session is not available already. My guess would be - the backend of your application loads data and closes the session, then you pass this data to frontend, for example, where there is no session already.
To resolve this, there are several possible ways to go:
Eager loading. Reliable, but possibly slow solution;
Changing the way session management is done. Consider strategy session-per-request which is suitable for typical web application. The question Create Hibernate-Session per Request contains information might be usable for you.
For information about another session management strategies, try reading this wiki page.
There are a few things that can assist you:
The use of Hibernate.initialize(customer.getAddresses())
You do not show where customer.getAddresses() is used ... so one other method is to use Hibernate Open Session in View (along with other session management strategies mentioned in the previous answer.
Suppose I have the class:
#Entity
public class Bean {
#Id
private String beanId;
//other fields & setters and getters
}
And the corresponding Spring Data JPA repository, where I want to have in a List<String> all the beanIds.
#RepositoryDefinition(domainClass = Bean.class, idClass = String.class)
public interface BeanRepository {
#Query("select b.beanId from Bean b")
List<String> findAllBeanId();
}
As written above, everything works as expected; but this is a simple operation and I do not want to write a query explicitly. What should the name of the method be such that Spring Data can parse it and obtain the above mentioned query (or the same functionality). I have searched in both the reference documentation as two books I have on Spring Data. The above name (findAllBeanId) and others that I have tried (findBeanId, findBeanBeanId etc.) throw the following exception as root cause:
org.springframework.data.mapping.PropertyReferenceException: No property find found for type Trade
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:271)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:245)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:72)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:180)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:260)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:240)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:68)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:57)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:90)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:68)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:279)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:147)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:153)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:43)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
... 22 more
In the Spring docs: http://static.springsource.org/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/jpa.repositories.html there is nothing about getting only particular column/property from entity by query generated from method name. So I think that currently it is not possible.
The code you showed works/should work as expected. It's simply not causing the exception you see :).
The exception is referring to a Trade, which seems to indicate that you have a repository for Trade somewhere which seems to refer to a missing property. The code you've shown is definitely not the one causing the exception. This can effectively not be the case as you're defining the query manually so that the query derivation mechanism doesn't even kick in for the repo you've shown.
I've pushed a test case for you to see this in action.