Nazila
Nazila

Reputation: 1453

How to lazy load collection in spring data?

I have an object model

@Table(name = "MOB_Objects")
public class ak_BankObject {
// private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

@ManyToOne
private ak_Zones ak_zone;

@OneToMany(cascade = CascadeType.ALL)
/* (mappedBy="brfebranchid") */
@JoinTable(name = "mob_bankObj_branchF")
List<ak_BranchFeatures> ak_branchFeatures;

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "mob_bankObj_image")
List<ak_BranchImages> ak_branchImages;

@OneToMany
List<ak_BranchScore> BranchScore;

@OneToMany
List<ak_BranchComment> BranchComment;

@Column
private Integer objectid;

@Column
private String branchname;

@Column
private String branchcode;

@Column
private Integer branchtype;

@Column
private String branchchief;

@Column
private String postalcode;

@Column
private Integer branchdegree;

@Column
private String branchtel;

@Column
private String branchfax;

@Column
private String branchtelbank;

@Column
private String address;

@Column
private Integer objecttype;

@Column
private double latitude;

@Column
private double longitude;

@Column
private String codedevices;

public ak_Zones getAk_zone() {
    return ak_zone;
}

public void setAk_zone(ak_Zones ak_zone) {
    this.ak_zone = ak_zone;
}

public List<ak_BranchFeatures> getAk_branchFeatures() {
    return ak_branchFeatures;
}

public void setAk_branchFeatures(List<ak_BranchFeatures> ak_branchFeatures) {
    this.ak_branchFeatures = ak_branchFeatures;
}

public String getBranchname() {
    return branchname;
}

public void setBranchname(String branchname) {
    this.branchname = branchname;
}

public String getBranchcode() {
    return branchcode;
}

public void setBranchcode(String branchcode) {
    this.branchcode = branchcode;
}

public Integer getBranchtype() {
    return branchtype;
}

public void setBranchtype(Integer branchtype) {
    this.branchtype = branchtype;
}

public String getBranchchief() {
    return branchchief;
}

public void setBranchchief(String branchchief) {
    this.branchchief = branchchief;
}

public String getPostalcode() {
    return postalcode;
}

public void setPostalcode(String postalcode) {
    this.postalcode = postalcode;
}

public Integer getBranchdegree() {
    return branchdegree;
}

public void setBranchdegree(Integer branchdegree) {
    this.branchdegree = branchdegree;
}

public String getBranchtel() {
    return branchtel;
}

public void setBranchtel(String branchtel) {
    this.branchtel = branchtel;
}

public String getBranchfax() {
    return branchfax;
}

public void setBranchfax(String branchfax) {
    this.branchfax = branchfax;
}

public String getBranchtelbank() {
    return branchtelbank;
}

public void setBranchtelbank(String branchtelbank) {
    this.branchtelbank = branchtelbank;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public Integer getObjecttype() {
    return objecttype;
}

public void setObjecttype(Integer objecttype) {
    this.objecttype = objecttype;
}

public Integer getObjectid() {
    return objectid;
}

public void setObjectid(Integer objectid) {
    this.objectid = objectid;
}

public String getCodedevices() {
    return codedevices;
}

public void setCodedevices(String codedevices) {
    this.codedevices = codedevices;
}

public double getLatitude() {
    return latitude;
}

public void setLatitude(double latitude) {
    this.latitude = latitude;
}

public double getLongitude() {
    return longitude;
}

public void setLongitude(double longitude) {
    this.longitude = longitude;
}

public List<ak_BranchComment> getBranchComment() {
    return BranchComment;
}

public void setBranchComment(List<ak_BranchComment> branchComment) {
    BranchComment = branchComment;
}

public List<ak_BranchScore> getBranchScore() {
    return BranchScore;
}

public void setBranchScore(List<ak_BranchScore> branchScore) {
    BranchScore = branchScore;
}

public List<ak_BranchImages> getAk_branchImages() {
    return ak_branchImages;
}

public void setAk_branchImages(List<ak_BranchImages> ak_branchImages) {
    this.ak_branchImages = ak_branchImages;
}

@Override
public String toString() {
    return "BankObject [id=" + id + ", lon=" + longitude + ", latitude="
            + latitude + "]";
}}

my Repository:

public interface BankRepository extends CrudRepository<ak_BankObject, Long> {}

my service:

@Service
public class BankService {
public List<ak_BankObject> searchInBbox(double minLon, double minLat, double maxLon,
            double maxLat) {

        List<ak_BankObject> banks = (List<ak_BankObject>) bankRepository.findAll();
        List<ak_BankObject> inBoxBanks = new ArrayList<>();

        for (int i = 0; i < banks.size(); i++) {
            double lon = banks.get(i).getLongitude();
            double lat = banks.get(i).getLatitude();
            if (lon >= minLon && lon <= maxLon && lat >= minLat
                    && lat <= maxLat) {
                inBoxBanks.add(banks.get(i));
            }
        }
        return inBoxBanks;
    }}

and with spring data I use crudRepository to find all in this object, but I have an error:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/MBFinder] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.spr.model.ak_BankObject.ak_branchFeatures, could not initialize proxy - no Session] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.spr.model.ak_BankObject.ak_branchFeatures, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:500)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at com.spr.model.ak_BankObject.toString(ak_BankObject.java:272)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at java.util.AbstractCollection.toString(Unknown Source)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at com.spr.controller.BankController.searchNearest(BankController.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

I don't want to use EAGER and I saw this Solution but didn't work for me,Is there a way instead of native query?

Upvotes: 1

Views: 3374

Answers (3)

Oliver Drotbohm
Oliver Drotbohm

Reputation: 83081

The easiest way is to simply mark your service method with @Transactional. That will cause the JPA EntityManager being held open until the code execution leaves the body of the method.

If you need to access lazy relationships outside of that method (e.g. when rendering a view), you need to deploy an OpenEntityManagerInViewFilter (based on the Servlet API) or the OpenEntityManagerInViewInterceptor (specific to Spring MVC).

Upvotes: 0

nuno
nuno

Reputation: 1791

If the OpenSessionInView solution, provided by sgyyz, doesn't work, you could explicitly initialize the lazy association.

 for (int i = 0; i < banks.size(); i++) {
        ak_BankObject bank = banks.get(i);
        Hibernate.initialize(bank.getAk_branchFeatures());
        double lon = bank.getLongitude();
        double lat = bank.getLatitude();
        if (lon >= minLon && lon <= maxLon && lat >= minLat && lat <= maxLat) {
            inBoxBanks.add(bank);
        }
    }

Since the OpenSessionInView would initialize the association one by one, I believe that in terms of performance this could be equivalent.

Offtopic: your object naming strategy is not the best. Your bank object should be within OO naming standards - AkBankObject (kept the Object in the name because it may be a business logic requirement, if not it could be named AkBank). The same for object properties, ak_branchFeatures --> akBranchFeatures. If you're dealing with legacy code, my condolences.

Upvotes: 0

Troy Young
Troy Young

Reputation: 191

Cause when you fetch the attribute in the lazy side, the session has been closed. So you can't get the attribute and you will receive the exception.

3 solution for you:

  1. change the fetch attribute as fetch = FetchType.EAGER.
  2. control the session scope by your code. means open the session from you fetch the attributes, after all the operation you done, then close it in the finally block.
  3. if you're APP is a web application, please use the OpenSessionInView filter to control the session scope automatically.

Upvotes: 1

Related Questions