For example I have three classes as follows
User{
Integer id;
...
}
Book{
Integer id;
....
#ManyToOne(fetch=FetchType.lazy)
User insertedBy;
}
Author{
Integer id;
List<Book> books;
}
Now I need to show the author list with their written books in same page
so I fetch authors with findAll() method using jpa repository. here I don't need the inserted by
column of books so I mad them with lazy load.
When I tried to converts these author lists into json object with Gson.
it gives lazy load exception in User class (Hibernate proxy... no session found.....)
I have followed many of the ways given in this network like TypeAdapters.
nothing helps me.
I just wanted to make insertedBy column of Books as null in lazy load.
for now I am using Dto classes to avoid insertedBy / make insertedBy as null.
Is there any other simple way without converting it into Dto.
I faced this issue many times. all those time I was end up with converting into Dto.
If anyone knows the answer please help me solve.
"lazy-load" in Hibernate means children does not actually get loaded when loading the parent, typically when you try to access a child during iteration it gets loaded. In your case you receive this lazy load exception because by the time when gson try to access the child to map it to a JSON object the session has closed already.
May be you can ask GSON to ignore that field while mapping to JSON by using ExclusionStrategy class provided by Gson.
I'm going to start a project of a REST application managed with Spring and with Hibernate for my model.
I know that Spring allows you to get Java object from the HTTP Request (with #Consumes(JSON) annotation). Is there any conflict if this Java object is also a Hibernate entities? And is nested object working (like #ManyToOne relation)?
Maven dependency
The first thing you need to do is to set up the following Hibernate Types Maven dependency in your project pom.xml configuration file:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Domain model
Now, if you are using PostgreSQL, you need to use the JsonType from Hibernate Types.
In order to use it in your entities, you will have to declare it on either class level or in a package-info.java package-level descriptor, like this:
#TypeDef(name = "json", typeClass = JsonType.class)
And, the entity mapping will look like this:
#Type(type = "json")
#Column(columnDefinition = "json")
private Location location;
If you're using Hibernate 5 or later, then the JSON type is registered automatically by the Postgre92Dialect.
Otherwise, you need to register it yourself:
public class PostgreSQLDialect extends PostgreSQL91Dialect {
public PostgreSQL92Dialect() {
super();
this.registerColumnType( Types.JAVA_OBJECT, "json" );
}
}
The JsonType works with Oracle, SQL Server, PostgreSQL, MySQL, and H2 as well. Check out the project page for more details about how you can map JSON column types on various relational database systems.
Yes, this wouldn't be a problem and is actually a fairly common practice.
In the recent years I have come to realize that sometimes, however, it is not a good idea to always build your views based on your domain directly. You can take a look at this post:
http://codebetter.com/jpboodhoo/2007/09/27/screen-bound-dto-s/
It is also known as "Presentation Model":
http://martinfowler.com/eaaDev/PresentationModel.html
The idea behind that is basically the following:
Imagine you have the domain entry User, who looks like that :
#Entity
#Data
public class User {
#Id private UUID userId;
private String username;
#OneToMany private List<Permission> permissions;
}
Let's now imagine you have a view where you wanna display that user's name, and you totally don't care about the permissions. If you use your approach of immediately returning the User to the view, Hibernate will make an additional join from the Permissions table because event though the permissions are lazily loaded by default, there is no easy way to signal to the jackson serializer or whatever you are using, that you don't care about them in this particular occasion, so jackson will try to unproxy them (if your transaction is still alive by the time your object is put for json serialization, otherwise you get a nasty exception). Yes, you can add a #JsonIgnore annotation on the permissions field, but then if you need it in some other view, you are screwed.
That a very basic example, but you should get the idea that sometimes your domain model can't be immediately used to be returned to the presentation layer, due to both code maintainability and performance issues.
We were using such approach to simplify design and get rid of many dtos (we were abusing them too much). Basically, it worked for us.
However, in our REST model we were trying to do not expose other relations for an object as you can always create another REST resources to access them.
So we just put #JsonIgnore annotations to relations mappings like #OneToMany or #ManyToOnemaking them transient.
Another problem I see that if you still like to return these relations you would have to use Join.FETCH strategy for them or move transaction management higher so that transaction still exists when a response is serialized to JSON (Open Session In View Pattern).
On my opinion these two solutions are not so good.
You can map the json request without using any library at REST web-services (Jersy)
this sample of code:
This hibernate entity called book:
#Entity
#Table(name = "book", schema = "cashcall")
public class Book implements java.io.Serializable {
private int id;
private Author author; // another hibernate entity
private String bookName;
//setters and getters
}
This web-services function
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String addBook(Book book) {
String bookName=book.getName();
return bookName;
}
This is sample json request:
{
"bookName" : "Head First Java",
"author" : {
"id" : 1
}
}
Since you are just starting, perhaps you could use Spring Data REST?
This is the project: http://projects.spring.io/spring-data-rest/
And here are some simple examples:
https://github.com/spring-projects/spring-data-book/tree/master/rest
https://github.com/olivergierke/spring-restbucks
As you can see in the examples, there are no extra DTOs beyond the #Entity annotated POJOs.
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.
I am writing an application that utilizes a database with a few many-to-one and one-to-many table relationships. I used the JBOSS tools in Eclipse to reverse-engineer the database and create the POJOs, and the getters and setters for the foreign-key relationships look something like this:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "users")
#LazyCollection(LazyCollectionOption.EXTRA)
public Set<Layouts> getLayoutses() {
return this.layoutses;
}
public void setLayoutses(Set<Layouts> layoutses) {
this.layoutses = layoutses;
}
The Sets in these cases are either empty HashSets or HashSets filled with POJOs representing another table in the database.
The problem is that the transform process chokes on the Set property. I get a javax.xml.transform.TransformerException: Error transforming result message if I leave the FetchType on "LAZY," and if I change it to "EAGER" I get no error message but no response from Struts2 either (the browser just keeps loading forever). If I change the Set getters to "protected" or "private" instead of "public," everything works without a hitch except, of course, for the fact that the result set will not contain those properties.
Everything I have read seems to indicate that Struts2 should be able to handle the Sets, but the only Struts2/Hibernate integration examples I have been able to find deal with extremely simple data containing no mapped, foreign key relationships.
What do I need to do in order to get the Struts2 xslt result type to play nicely with my Hibernate persistence objects?
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!