Jersey API + JPA/Hibernate Criteria Lazy Loading not working - java

Here is a simplified POJO i have:
#Entity
#Table( name = "Patient" )
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn
(
name="Discriminator",
discriminatorType=DiscriminatorType.STRING
)
#DiscriminatorValue(value="P")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Patient implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID", unique = true, nullable = false)
protected Integer ID;
#ManyToOne(targetEntity = TelephoneType.class, fetch=FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="IDPhoneType")
protected TelephoneType phoneType;
#JsonProperty(required=false, value="phoneType")
public TelephoneType getPhoneType() {
return phoneType;
}
public void setPhoneType(TelephoneType phoneType) {
this.phoneType = phoneType;
}
}
Now here is my class TelephoneType:
#Entity
#Table( name = "TelephoneType" )
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
#JsonAutoDetect(getterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE, fieldVisibility=Visibility.NONE)
public class TelephoneType implements Serializable{
private static final long serialVersionUID = -3125320613557609205L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID", unique = true, nullable = false)
private Integer ID;
#Column(name = "Name")
private String name;
#Column(name = "Description")
private String description;
public TelephoneType() {
}
#JsonProperty(value="id")
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
#JsonProperty(value="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonProperty(value="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
The reason i use the #JsonAutoDetect annotation in TelephoneType is first to customize the json property names (i needed to deactivate the default jsonautodetect) and also because if I don't, I get an error when fetching the Queue
No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: my.package.Patient["phoneType"]->my.package.TelephoneType_$$_jvste17_13["handler"])
So without the #JsonAutoDetect annotation i get the error and with the annotation no Lazy Loading occurs and the TelephoneType is always loaded in the json response.
I use Criteria to make the query:
return this.entityManager.find(Patient.class, primaryKey);
I also added, as I read in different posts on so, the following in the web.xml of my application (Jersey API):
<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Now somehow I surely missed something in my configuration but can't figure out what and we have many #ManyToOne relationships in the db that are slowing down the api considerably (some heavier objects than the one I showed in the example) so I would really appreciate to find a way to activate this lazy loading thing...

If you are using JSON then I presume that you are supplying the results through a REST endpoint. What is happening then is you are passing the Patient entity back to the REST service. When the REST service, Jersey in this case, serializes the Patient entity it touches all of the properties, and even walks through them, so as to build as complete a tree as possible. In order to do this, every time Jersey hits a property that's not yet initialized, Hibernate makes another call back to the database. This is only possible if the EntityManager is not yet closed.
This is why you have to have the OpenEntityManagerInViewFilter installed. Without it, the EntityManager is closed when you exit the service layer and you get a LazyInitializationException. The OpenEntityManagerInViewFilter opens the EntityManager at the view level and keeps it open until the HTTP request is complete. So, while it seems like a fix, it's not really because, as you see, when you lose control over who is accessing the properties of your entities, in this case Jersey, then you end up loading things you didn't want to load.
It's better to remove the OpenEntityManagerInViewFilter and figure out what exactly you want Jersey to serialize. Once you have that figured out, there are at least two ways to go about handling it. IHMO, the "best practice" is to have DTO, or Data Transfer Objects. These are POJOs that are not entities but have pretty much the same fields. In the case, the PatientDTO would have everything except the phoneType property (or maybe just the Id). You would pass it a Patient in the constructor and it would copy the fields you want Jersey to serialize. Your service layer would then be responsible for returning DTO's instead of Entities, at least for the REST endpoints. Your clients would get JSON graphs that represent these DTOs, giving you better control over what goes into the JSON because you write the DTOs separate from the Entities.
Another option is to use JSON annotations to prevent Jersey from attempting to serialize properties you don't want serialized, such as phoneType, but that ultimately becomes problematic. There will be conflicting requirements and you never get it sorted out well.
While making DTO's at first seems like a horrible pain, it's not as bad as it seems and it even helps when you want to serialize values that are more client friendly. So, my recommendation is to lose the OpenEntityManagerInViewFilter and construct a proper service layer that returns DTOs, or View Objects as they are sometimes called.
References: What is Data Transfer Object?
REST API - DTOs or not?
Gson: How to exclude specific fields from Serialization without annotations

To understand what is happening here you have to understand how lazy loading works in Hibernate.
When a list is declared as "lazy loaded" the Hibernate framework implements a "lazy loaded" JavassistLazyInitializer object with Javassist.
Hence, the phoneType on your patient object is not an implementation of your TelephoneType class. It is a proxy towards it.
When getPhoneType() on this object is called however, the proxy on patient is replaced by the real object.
Unfortunately, #JsonAutoDetect uses reflection on the proxy object without ever calling getPhoneType() and tries to actually serialise the JavassistLazyInitializer object which of course is impossible.
I think the most elegant solution for this is to implement a query that fetches the patients with their telephoneType.
So instead of:
return this.entityManager.find(Patient.class, primaryKey);
Implement something like:
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Patient> query = cb.createQuery(Patient.class);
Root<Patient> c = query.from(Patient.class);
query.select(c).distinct(true);
c.fetch("phoneType");
TypedQuery<Patient> typedQuery = em.createQuery(query);
List<Patient> allPatients = typedQuery.getResultList();
Adapting the query to your needs as required.

Have a look at jackson-datatype-hibernate
It makes the json serialization with jackson 'aware' of the hibernate proxy

Related

One way mapping in Dozer using custom converter

Please note: while I would accept an XML-based solution if that's truly the only way to accomplish what I'm looking for, I would greatly prefer a solution using Dozer's Java API.
I am new to Dozer and am trying to figure out how to use its API. It seems to default to field-level mappings (if the field names match) and to allow for custom mappers and converters in the event that field-level mapping (based on field name) is either not possible or not logical for your application needs.
I have a situation where my app will take a DTO, say, ReportedIssue (an issue reported by a user and sent to my application over HTTP), and an Issue entity (a data entity that will be persisted to a MySQL DB).
Here are my two objects:
#Data
public class ReportedIssue {
private String typeRefId;
private String reporterRefId;
private String info;
}
#Entity
#Table(name = "issues")
#Data
public class Issue {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "issue_ref_id")
private String refId;
#Column(name = "issue_tracking_number")
private String trackingNumber;
#OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name = "issue_type_id", referencedColumnName = "issue_type_id")
private IssueType type;
#Column(name = "issue_reported_on")
private Date reportedOn;
#OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name = "issue_reporter_id", referencedColumnName = "account_id")
private Account reporter;
#Column(name = "issue_info")
private String info;
}
So in the application frontend, a user can report an issue. The frontend sends a JSON version of a ReportedIssue to the backend, where that JSON is deserialized into a ReportedIssue DTO bean. Then I need Dozer to convert my ReportedIssue into an Issue entity that I can then easily save to my MySQL DB.
Here is my best attempt:
public class ReportedIssueConverter extends DozerConverter<ReportedIssue, Issue> {
private AuthService authService;
public ReportedIssueConverter(AuthService authService, Class<ReportedIssue> prototypeA, Class<Issue> prototypeB) {
super(prototypeA, prototypeB);
this.authService = authService;
}
public ReportedIssueConverter(Class<ReportedIssue> prototypeA, Class<Issue> prototypeB) {
super(prototypeA, prototypeB);
}
#Override
public Issue convertTo(ReportedIssue source, Issue destination) {
Issue issue = new Issue();
issue.setRefId(UUID.randomUUID().toString());
issue.setType(IssueUtils.determineType(source));
issue.setReportedOn(DateTimeUtils.nowInUTC());
issue.setReporter(authService.currentUser());
issue.setInfo(destination.getInfo());
return issue;
}
#Override
public ReportedIssue convertFrom(Issue source, ReportedIssue destination) {
throw new UnsupportedOperationException("we currently don't map from issues to reported issues");
}
}
Several concerns here. For one, is such a custom converter even necessary? Or is there a "better" (more standards compliant or using generally-accepted Dozer practices) way to use the Dozer API to perform this conversion? But mainly, this DozerConverter seems to be intended for bi-directional mapping use cases. Whereas, in my application, I will never have an Issue instance and need to map it back to a ReportedIssue DTO instance. So I only need one-way mapping from ReportedIssue --> Issue. Am I using Dozer correctly by throwing an UnsupportedOperationException or is there another interface or API trick I can use to only leverage the one-way mapping I need?
It could actually be done without a custom converter using custom getter methods in your dto class corresponding to fields in Issue. Dozer works by mapping each field in destination class by trying to invoke the getter method of the corresponding name in the source class.
public class ReportedIssue {
// fields.......
public String getRefId() {
UUID.randomUUID().toString()
}
public IssueType getType() {
IssueUtils.determineType(this);
}
// similarly create getters for other required fields.
}
But for reporter field in Issue, you need an AuthService object. I would suggest writing a static method as below:
public static Issue getIssue(AuthService auth, ReportedIssue dto) {
Issue issue = //map using dozer
issue.setReporter(authService.currentUser());
return issue;
}
Gauntham answer will work. Another option:
Implement a com.github.dozermapper.core.BeanFactory
Your custom BeanFactory can handle
Issue issue = new Issue();
issue.setRefId(UUID.randomUUID().toString());
issue.setReportedOn(DateTimeUtils.nowInUTC());
issue.setReporter(authService.currentUser());
Then depending on your preferences, this could also go into the bean factory
issue.setType(IssueUtils.determineType(source));
Or you could handle that separately in the mapping. Something would need to know how to call IssueUtils, so that is either 1) a customer converter or 2) a change to the DTO or entity to have the functionality through a getter or setter.
Finally, this line would be handled in the Dozer Java API mapping
issue.setInfo(destination.getInfo());
Personally, I like Dozer's com.github.dozermapper.core.loader.api.BeanMappingBuilder where you can explicitly tell it how to map 2 beans, specify the bean factory to use and the custom converter for a specific field.
mapping(ReportedIssue.class, Issue.class, oneWay(), wildcard(true), beanFactory(IssueBeanFactory.class.getName()).fields("this", "type", customConverter(IssueTypeConverter.class)
oneWay(), wildcard(boolean), and beanFactory(String) are found in Dozer's TypeMappingOptions and customConverter(Class.class) is found in Dozer's FieldMappingOptions.
oneWay() makes the mapping work only in the direction specified in the BeanMappingBuilder.
wildcard(true) tells Dozer to automatically map matching fields (this is default behavior).

Getting infinite Json response when using many to one mapping in spring [duplicate]

This question already has answers here:
Infinite Recursion with Jackson JSON and Hibernate JPA issue
(29 answers)
Closed 3 years ago.
I am trying to create Many to one mapping between two entities in spring. However when I try to fetch the values using a restController I get
Java.lang.IllegalStateException: Cannot call sendError() after the
response has been committed
error and an infinite JSON response. Adding JSON ignore solves this issue but then I don't get that column in my response at all. I don't know how to fix this. Please help. Thanks in advance.
Here are my entities:
#Entity
#Table(name="tbl1")
public class Data {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "customer")
private String customer;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="data_id", insertable = true, nullable = false, updatable = false)
private DataList dataList1;
}
#Entity
#Table(name="tbl2")
public class DataList {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="data_id")
private Long dataId;
#Column(name="user_name")
private String userName;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,mappedBy = "dataList1")
private List<Data> data1;
}
Repositories:
#Repository
#Transactional
public interface DataList extends JpaRepository<DataList,Long> {
}
#Repository
#Transactional
public interface Data extends JpaRepository<Data,Long> {
}
My error: Java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
1) In general putting fetch = FetchType.EAGER on #OneToMany is not an advisable practice. Try to set it to LAZY instead.
2) Make sure that Data and DataList entities properly implement equals() and hashCode() methods.
It is happening as JSON serializer is trying to serialize both the entities recursively again and again.
So, while serializing Data, its member dataList1 is of type DataList which further contains List<Data>, this loop will be infinite.
Ideally, in such scenarios, the entities should be mapped to some other model meant for the serialization and response or one of the model needs to be #JsonIgnore to avoid this recursive loop going.
EAGER is a bad practice. Use LAZY, and when you need the related entities, use fetch join query.
Most likely the problem here in the bi-directional relation. You fetch DataList with Data list. And each Data in List ListData refers again.
More likely here to be a stack overflow when serializing json. So remember one rule: never give in controllers hibernate entities. Write a mapper for map this entities to Dto objects.
You may think that it is extremely boring to map some models to another. But here in another way. Hibernate entities should not be passed to front end. My application uses several types of objects: Entities (when fetch from DB), DTO (When map entities to DTO and give their in service components), Shared (when map DTO to Shared and share as a response to the controller between my microservices) and Model (when map from Response to Model and give to the template engine, for example freemarker). You may not need this hierarchy of models.
Create DTO's:
#AllArgsConstructor
#NoArgsConstructor
#Getter
public class DataListDto {
private Long dataId;
private String userName;
private List<DataDto> data1;
}
#AllArgsConstructor
#NoArgsConstructor
#Getter
public class DataDto {
private long id;
private String customer;
}
write your mapper:
public class DataListMapper {
public static DataListDto mapToDto(DataList dataList) {
return new DataListDto(dataList.getDataId(), dataList.getUserName(), dataList.getData1().stream().map(x -> DataListMapper.mapToDto(x).collect(Collectors.toList)))
}
public static DataDto mapToDto(Data data) {
return new DataDto(data.getId(), data.getCustomer());
}
}
your service:
public class DataListService {
#Autowired
private DataListRepository dataListRepository;
public List<DataListDto> getAllData() {
List<DataList> dataLists = this.dataListRepository.findAll();
return dataLists.stream().map(x->DataListMapper.mapToDto(x)).collect(Collectors.toList());
}
}

Crnk JsonApiRelation, OneToMany and filtering implementation

I use crnk (JSON-API) in java project and I have 3 questions regarding its usage with spring boot and jpa - haven't found exact implementation details in documentation.
For example, I have 2 entities and respective tables:
#Entity
#JsonApiResource(type = "employee")
public class Employee {
#Id
#JsonApiId
private int id;
private String name;
#ManyToOne
#JoinColumn(name = "typeId")
private EmployeeType employeeType; //stored in table as typeId
}
#Entity
#JsonApiResource(type = "type")
public class EmployeeType {
#Id
#JsonApiId
private int id;
private String typeName;
private int salary;
}
How should JsonApiRelation be introduced in order to be able to call "/employee/1" and "/employee/1/type" urls?
For example there is one more entity.
#Entity
#JsonApiResource(type = "project")
public class Project {
#Id
#JsonApiId
private int id;
private String supervisorName;
private String projectName;
}
First, I'd like to have List of Projects for each Employee, where he is a supervisor, joint by name and have it listed as attribute in Json.
Tried implementing it with #OneToMany and #JoinColumn annotations but got StackOverflowException. How could this be implemented. And second, how could this be implemented with Relation? Like "/employee/1/projects" url.
How should I implement custom filtering of results for findAll method? For example, I have a List of all Employees, but I'd like to exclude some of them from the response. Which class/method should be introduced for this behaviour?
#JsonApiRelation annotation should not be necessary. Crnk will detect the #ManyToOne annotation and map it accordingly.
in case of crnk-jpa it is sufficient to specify all relationships in JPA. Matching JSON API relationships. So your approach seems good. What was the StackoverflowException stacktrace? (next to the examples, there are also many example entities in crnk-jpa)
I would make use of a decorator. See http://www.crnk.io/documentation/#_request_filtering. RepositoryDecoratorFactory allows to place a custom repository between the caller and crnk-jpa (or any other kind of repository). There you can do any kind of modification perform (maybe) calling the "real" repository. => Will add an example for this
feel free also make open up tickets in crnk for any documentation/example clarifications.

Why Nested Objects is retrieved from JPA? [duplicate]

I'm using SpringBoot and JPA to build a REST interface.
Now, I have a strange JSON returned for the list of products fetched from the database. Let's say that I have:
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "categoryId", nullable = false, updatable = false)
private Category category;
...
}
#Entity
public class Category implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(mappedBy = "category", cascade = CascadeType.DETACH)
#OrderBy("name ASC")
private List<Product> products = Collections.emptyList();
...
}
The JPA repository for the Product is defined as:
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findAll();
}
In my controller I have:
#Autowired
private ProductRepository productRepo;
#RequestMapping("/all-products", method = RequestMethod.GET)
public Map<String,Object> home() {
Map<String,Object> model = new HashMap<String,Object>();
model.put("products", productRepo.findAll());
return model;
}
What is driving my crazy, is that if I try to call this service as follows:
$ curl localhost:8080/all-products
I get a recursive output due to the relationship between tables product and category, e.g.:
{"products":[{"id":1,"name":"Product1","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,...
What am I doing wrong?
You're not doing anything wrong (at least at the code level it's rather conceptual) - json serializer just goes like this:
Product - serialize it, but wait - there is a category field, so serializer must serialize the category field
Category - serialize it, but wait - there is a products field, so serializer must serialize each of the product in the list
Product - because your collection contains the product & product contains category it goes in a endless loop untill a timeout.
You must use a view or just skip it.
Use #JsonView
Use a view as a POJO
Return new ProductView that has all fields of product and a reference (category) to new CategoryView (you can end at this point) that has collection of (products) new ProductViewWithoutReferences, and so on
Use #JsonIgnore on a collection of products
And as a side note - if it's a #RestController and you're invoking "all-products" then it's a bit unusual to return something else than a list. Wrapping the response in a map is redundant. Many rest clients expect a list when they invoke list() method.
I know it's a bit late, but adding it here in case anybody faces the same problem.
Here is another relevant answer I could find which discuss about similar topic
https://stackoverflow.com/a/3359884/6785908
quoting it here
Jackson 1.6 has annotation-based support for handling such
parent/child linkage, see
http://wiki.fasterxml.com/JacksonFeatureBiDirReferences.
You can of course already exclude serialization of parent link already
using most JSON processing packages (jackson, gson and flex-json at
least support it), but the real trick is in how to deserialize it back
(re-create parent link), not just handle serialization side. Although
sounds like for now just exclusion might work for you.
EDIT (April 2012): Jackson 2.0 now supports true identity
references, so you can solve it this way also.
Adding #JsonIgnore worked for me
#OneToMany(mappedBy = "policy")
#JsonIgnore
private List<Payment> payments;
#JeanValjean your are the best

Lazy load doesn't work - I Only need the parent object, not all associations

How do get the object I want, without all of the child associations.
I have my class Site:
#Entity
#Table(name = "Sites")
public class Site {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Id_Site", unique = true, nullable = false)
private long Id_Site;
private String ...;
private boolean ...;
private long ...;
private Date ...;
private Date ...;
private String ...;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Sequence> sequences = new HashSet<>();
#ManyToOne
private ... ...;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<...> ... = new HashSet<>();
#ManyToOne
private ... ...;
public constructor...
public set..
public get..
}
I only need a Site object, without the Sequence Associations.
In my Sequence Table, I have:
#Entity
#Table(name = "Sequences")
public class Sequence {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Id_Sequence", unique = true, nullable = false)
private long Id_Sequence;
private Date ....;
private Date ....;
private String ....;
private String ....;
private String ....;
private int ....;
private int ....;
private double ....;
private double ....;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<TraceSequence> traceSequences = new HashSet<>();
#ManyToOne(cascade = CascadeType.ALL)
private Site site;
public constructor...
public set..
public get..
}
When I use FetchType.Lazy, and call my method:
#Override
public Site findSiteByName(String Name_Site) {
List<Site> sites = entityManager.createQuery("SELECT s FROM Site s").getResultList();
for (Site item : sites) {
if (item.getNom_Site().equals(Name_Site)) {
return item;
}
}
return null;
}
I get this error:
failed to lazily initialize a collection of role: xxx.xxx.xxx.xxx.xxx.site.Site.sequences, could not initialize proxy - no Session
When I use FetchType.EAGER, I get not only a Site object, but I also get all sequence objects, and all objects of other sequence associations. (I know it is the normal response.)
Could someone who knows why this attempt at lazy initialization doesn't work, please, tell me how to resolve this problem.
These lazy errors happens when the jpa tries to get the data after the session is closed.
But using eager will influence all the queries that include that entity.
Try to use a join fetch in the query instead of the eager.
Somewhere in your code you are calling Site.GetSequences(), maybe iterating in the view or in another part of your code. It doesn't look like the piece of code you gave are generating the exception.
I you try to use a collection that is not loaded to your entity, the code throws the exception you mentioned.
To solve this, identify where you are using the sequences and load them before you use by changing the fetch to EAGER or using the JOIN FETCH in your query.
Returning a hibernate managed entity (or a collection of hibernate managed entities) will most likely cause these sort of problems unless you are super cautious on what is being returned and what was populated by hibernate when session was available.
I would say create a DTO (or a collection of DTO) and populate its fields the way you like. There are many Entity to DTO conversion framework; my fav is ModelMapper.
I also tend to agree with other suggestions to play with FetchType but since DTOs are populated by us we know what we populated as opposed to entity-relationships which are populated by hibernate based on annotations.
If you need something in the DTO you simply ask the entity and since session would be available at that point of time you could populate any field that you think you would need on the UI.
I don't want to hijack this topic towards DTO and Entity but that's how I would do it.
This may be helpful too Avoid Jackson serialization on non fetched lazy objects
Error happen becouse you try execute getSequences(), but becouse of is lazy and session is alredy closed hibernate rais the error.
To avoid this error read read sequencese inside query method, "inside" session, like this:
public Site findSiteByName(String Name_Site) {
List sites = entityManager.createQuery("SELECT s FROM Sites").getResultList();
for (Site item : sites) {
if (item.getNom_Site().equals(Name_Site)) {
item.getSites();
return item;
}
}
return null;
}
This is a lazy loading, you read collenction just when you need it!
As stated by other SE members above, you are getting this error because session is already closed.
If you want to load a particular object then you can use Hibernate.initialize method. it will execute one additional query to fetch the data of related entity.
Therefore, it is as per need basis and will not be executed all times as compared to Eager loading
I'm working on a project that aims to solve common JPA problems when mapping entities to DTOs using ModelMapper. This issue has already been solved on the project. Project link: JPA Model Mapper
On this scenario I believe that we'd want to simply get null for all lazy load entities. For this question specifically, this could be done by using de JPA Model Mapper to map an entity to DTO.
I've already answered the same issue on this question: How to solve the LazyInitializationException when using JPA and Hibernate

Categories