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 wondering what's the best practice when using a PUT method to update a specific property of an entity stored in DB.
Let's see for example the following json that is received on the Rest Controller:
{"id":1, "surname":"Doe"}
The entity that we have stored looks something like this:
public class Employee {
Long id;
String name;
String surname;
Date createdAt;
Date updatedAt;
}
I omitted the annotations for simplicity purposes.
What I'd like to achieve is that on the RestController I receive something like this:
#PutRequest
public Employee updateEmployee(#RequestBody Employee employee) {
repo.saveAndFlush(employee);
}
So, if I do it, then the existing fields for the name and timestamps will be set to null because the provided entity doesn't contain such fields.
I'm wondering if there's a way to run the following actions:
Load the entity with the ID provided on DB
Update the fields provided in the Json/Request Body.
Persist the updated entity -> This can be done the same way I've showed in the code.
I'm aware that it exists the #JsonIdentity and #JsonIdentifyreference(alwaysAsId=true) which I use in conjunction with resolvers to fetch the data from DB for fetching a nested entity where only the ID is provided rather the entity itself.
PATCH method is designed for that functionality.
PUT should be used when you are replacing the whole resource - that means setting null on fields that you didn't provide in request.
PATCH is used for updating a resource, you can update a single field, or all the fields, your choice.
Be aware that the actual database update may not automagically work, just because you changed the HTTP method. For Hibernate there is a #DynamicUpdate that provides the same functionality. Without #DynamicUpdate the fields set to null will be updated, but with #DynamicUpdateonly the fields that were modified will be updated.
I have a Pojo:
class Pojo{
String name;
String surname;
}
and a jpa/hibernate entity:
class Entity{
Long id;
String code;
List<EntityPojo> ep;
}
finally the entity pojo
class EntityPojo{
Long id;
String name;
String surname;
}
In my code I do:
//I receive a pojo from the rest call and I want to update
Entity entity = repo.findByCode("aCode");
//at this point my entity pojo IDs are correctly filled!
dozerMapper.map(pojo, entity);
//after the map the IDs are null!!
repo.save(entity); //BAM!
As you can see the mapping just deletes the IDs and this brings me to the constraint exception in hibernate...why is that?
You didn't provide a code that isolates and reproduce the problem.
From what you provided, at least things to check:
1) What id is in pojo instance? If it's null - here your result. Could be useful: Exclude Mapping Null Values
2) Check access levels. I'm not sure how Dozer currently working if fields are not public and have no public access methods.
3) Did you verify that fields are in the entity are null, not in a database? If you do - why this question has spring-data-jpa tag and code related to persistency level? If you don't - why are you sure that something wrong with Dozer, not with your database mapping?
In general - you don't seem to work on the question by yourself at all, because if you do - you would at least make an example with cleaned up database persistence layer after checking that it's not a place where you lose your fields. It's really hard to answer a question with mix of technologies and problem could be anywhere.
I have developed a spring rest service which will accepts a json input and freeze the details in to database and return the status as json output. everything is working fine.
now i need to update the service with the new requirement, i will get address details of the user and i need to update the address table as well. My question is
1) How to change the input request currently my controller is as follows
#Requestmappping(value="/register", metod=RequestMethod.POST)
public #ResponseBody ResponseEntity userRegis(#RequestBody UserBean userdetails){
}
2) How to change the UserBean format. Currently it is mapping to one single table. Now i need to update the bean with address fields. and i need to map the address fields to new table.
please help on this.
What you are referring to in composition in OOP. So, basically user has address or addresses.
class User {
....
private Address addres;
//private List<Address> addres; use something like this if user has multiple addesses
}
class Address {
}
And offcourse you would not want to map same bean to multiple tables or something like that. The above relation is simple parent child relation. Read here
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.