5

Sprężyna sprężyn powrotnych MVC i sprężyna danych, sprężyna bezpieczeństwa. Przedni koniec Angularjs.I'm using spring 3.1; Jackson 1.8; JPa 2.1 ands mysql. Podstawowy problem jest taki sam jak pytanie zadawane wiele razy. Mam prosty program z dwoma obiektami POJO i typSite-, gdzie typSite może mieć wiele witryn. Ale ja otrzymuję następujący błąd:Jackson pomylił się z dwukierunkową relacją jeden do wielu: nie udało się leniwie zainicjować kolekcji

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: TypeSites.sitees, could not initialize proxy - no Session (through reference chain: vo.TypeSitesListVO["typesites"]->java.util.UnmodifiableRandomAccessList[0]-model.TypeSites["sitees"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: model.TypeSites.sitees, could not initialize proxy - no Session (through reference chain:vo.TypeSitesListVO["typesites"]->java.util.UnmodifiableRandomAccessList[0]->model.TypeSites["sitees"]) 
Caused by: com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: model.TypeSites.sitees, could not initialize proxy - no Session (through reference chain: vo.TypeSitesListVO["typesites"]->java.util.UnmodifiableRandomAccessList[0]->model.TypeSites["sitees"]) 

i to następujący błąd w przeglądarce:

Failed to load resource: the server responded with a status of 500 (Internal Server Error) 

Więc lepiej zrozumieć ten błąd przyjrzyjmy się, jak JPA/Hibernate obsługuje związek. Za każdym razem, gdy robimy zapytanie w bazie danych, WZP przekaże wszystkie informacje o tej klasie. Wyjątkiem od tej reguły jest sytuacja, gdy mówimy o liście (kolekcji). Należy zauważyć w powyższym kodzie, że zapytanie bazy danych zwróci obiekt Sites. Kiedy wchodzę do zbioru witryn, kontener zauważy, że kolekcja witryn jest leniwym atrybutem i "poprosi" WZP o załadowanie tej kolekcji z bazy danych.

W momencie wykonania zapytania (które spowoduje wykonanie zbioru witryn) wystąpi wyjątek. Kiedy JPA/Hibernate spróbuje uzyskać dostęp do bazy danych, aby uzyskać te leniwą informację, JPA zauważy, że nie ma otwartej kolekcji. Dlatego dzieje się wyjątek, brak otwartego połączenia z bazą danych.

modelu klasy:

@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" }) 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id") 
public class Sites implements java.io.Serializable { 

    private static final long serialVersionUID = 1L; 
    private int     id; 
    private TypeSites   siteesTypeSite; 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    public int getId() { 
     return id; 
    } 
    //@ManyToOne(fetch = FetchType.LAZY) 
    //@JoinColumn(name ="idTypeSite") 
    //@JsonIgnore 
    @JsonBackReference("site-typeSite") 
    @ManyToOne 
    @JoinColumn(name = "idTypeSite", foreignKey = @ForeignKey(name = "fk_site_typeSite")) 
    public TypeSites getSiteesTypeSite() { 
     return siteesTypeSite; 
    } 
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" }) 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="idTypeSite") 
public class TypeSites implements java.io.Serializable { 
    private int      idTypeSite; 
    private Set<Sites>    sitees= new HashSet<Sites>(0); 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    public int getIdTypeSite() { 
     return idTypeSite; 
    } 
    //@JsonSerialize(using = CustomListSerializer.class) 
    //@JsonView(Views.Internal.class) 
    //@JsonIgnore 
    @JsonManagedReference("site-typeSite") 
    @OneToMany(mappedBy = "siteesTypeSite", cascade = CascadeType.ALL,fetch = FetchType.LAZY) 
    public Set<Sites> getSitees() { 
     return sitees; 
    } 

kod obiektu wartość wzorca projektowego

public class TypeSitesListVO { 
    private int   pagesCount; 
    private long  totalTypeSite; 
    private String  actionMessage; 
    private String  searchMessage; 
    private List<TypeSites> typesites; 
    //setters/gtters} 
public class SitesListVO { 
    private int pagesCount; 
    private long totalSites; 
    private String actionMessage; 
    private String searchMessage; 
    private List<Sites> sites = new ArrayList<Sites>(); 
    //setters/gtters} 

Repozytorium:

public interface SitesRepository extends PagingAndSortingRepository<Sites, Integer> { 
    //@Query("SELECT s FROM Sites s TypeSites ts JOIN FETCH s.siteesTypeSite WHERE s.id =ts.idTypeSite ") 
    //@EntityGraph(value = "sites.type", type = EntityGraphType.LOAD) 
    Page<Sites> findBycodeGSMLike(Pageable pageable, String codeGSM); 
    //Page<Sites> findBycodeGSMLike(Pageable pageable, List<String> codeGSM); 
} 

Usługi klasa:

@Service 
@Transactional 
public class SitesService { 
    @Autowired 
    private SitesRepository siteRepository; 
    @Transactional(readOnly = true) 
    public SitesListVO findAll(int page, int maxResults) { 
     Page<Sites> result = executeQueryFindAll(page, maxResults); 
       if(shouldExecuteSameQueryInLastPage(page, result)){ 
       int lastPage = result.getTotalPages() - 1; 
    //   for (Sites e: result){ 
    //    Hibernate.initialize(e.getSiteesTypeSite()); 
    //   } 
       result = executeQueryFindAll(lastPage, maxResults); 
      } 
      return buildResult(result); 
     } 
     public void save(Sites site) { 
      siteRepository.save(site); 
     } 
     @Transactional(readOnly = true) 
     public SitesListVO findBycodeGSMLike(int page, int maxResults, String codeGSM) { 
      Page<Sites> result = executeQueryFindByName(page, maxResults, codeGSM); 

      if(shouldExecuteSameQueryInLastPage(page, result)){ 
       int lastPage = result.getTotalPages() - 1; 
    //   for (Sites e: result){ 
    //    Hibernate.initialize(e.getSiteesTypeSite()); 
    //   } 
       result = executeQueryFindByName(lastPage, maxResults, codeGSM); 
      } 
      return buildResult(result); 
     } 
     private boolean shouldExecuteSameQueryInLastPage(int page, Page<Sites> result) { 
      return isUserAfterOrOnLastPage(page, result) && hasDataInDataBase(result); 
     } 
     private Page<Sites> executeQueryFindAll(int page, int maxResults) { 
      final PageRequest pageRequest = new PageRequest(page, maxResults, sortBycodeGSMASC()); 
    //  Page<Sites> SitesList = siteRepository.findAll(pageRequest); 
    //  for (Sites e: SitesList){ 
    //   Hibernate.initialize(e.getSiteesTypeSite()); 
    //  } 
    //  return SitesList; 
      return siteRepository.findAll(pageRequest); 
     } 

     private Sort sortBycodeGSMASC() { 
      return new Sort(Sort.Direction.ASC, "codeGSM"); 
     } 

     private SitesListVO buildResult(Page<Sites> result) { 

      return new SitesListVO(result.getTotalPages(), result.getTotalElements(), result.getContent()); 
     } 

     private Page<Sites> executeQueryFindByName(int page, int maxResults, String codeGSM) { 
      final PageRequest pageRequest = new PageRequest(page, maxResults, sortBycodeGSMASC()); 

    //  Page<Sites> SitesList = siteRepository.findBycodeGSMLike(pageRequest, codeGSM); 
    //  for (Sites e: SitesList){ 
    //   Hibernate.initialize(e.getSiteesTypeSite()); 
    //  } 
    //  return SitesList; 
      return siteRepository.findBycodeGSMLike(pageRequest, codeGSM); 
     } 
     private boolean isUserAfterOrOnLastPage(int page, Page<Sites> result) { 
      return page >= result.getTotalPages() - 1; 
     } 

     private boolean hasDataInDataBase(Page<Sites> result) { 
      return result.getTotalElements() > 0; 
     } 
    } 
Klasa

kontroler: Kod

@Controller 
@RequestMapping(value = "/protected/sites") 
public class SitesController { 
    private static final String DEFAULT_PAGE_DISPLAYED_TO_USER = "0"; 
    @Autowired 
    private SitesService siteService; 
    @Autowired 
    private MessageSource messageSource; 

    @Value("5") 
    private int maxResults; 

    @RequestMapping(method = RequestMethod.GET) 
    public ModelAndView welcome() { 
     return new ModelAndView("sitesList"); 
    } 
    @RequestMapping(method = RequestMethod.GET, produces = "application/json") 
    public ResponseEntity<?> listAll(@RequestParam int page, Locale locale) { 

     return createListAllResponse(page, locale); 
    } 

    @RequestMapping(method = RequestMethod.POST, produces = "application/json") 
    public ResponseEntity<?> create(@ModelAttribute("site") Sites site, 
            @RequestParam(required = false) String searchFor, 
            @RequestParam(required = false, 
            defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page, 
            Locale locale) { 
     siteService.save(site); 

     if (isSearchActivated(searchFor)) { 
      return search(searchFor, page, locale, "message.create.success"); 
     } 

     return createListAllResponse(page, locale, "message.create.success"); 
    } 


    private SitesListVO listAll(int page) { 
     return siteService.findAll(page, maxResults); 
    } 
    private ResponseEntity<SitesListVO> returnListToUser(SitesListVO siteList) { 
     return new ResponseEntity<SitesListVO>(siteList, HttpStatus.OK); 
    } 
    private ResponseEntity<?> createListAllResponse(int page, Locale locale) { 
     SitesListVO siteListVO = listAll(page); 
     return createListAllResponse(page, locale, null); 
    } 

    private ResponseEntity<?> createListAllResponse(int page, Locale locale, String messageKey) { 
     SitesListVO siteListVO = listAll(page); 
     addActionMessageToVO(siteListVO, locale, messageKey, null); 
     return returnListToUser(siteListVO); 
    } 
    private SitesListVO addActionMessageToVO(SitesListVO siteListVO, Locale locale, String actionMessageKey, Object[] args) { 
     if (StringUtils.isEmpty(actionMessageKey)) { 
      return siteListVO; 
     } 
     siteListVO.setActionMessage(messageSource.getMessage(actionMessageKey, args, null, locale)); 
     return siteListVO; 
    } 
    private SitesListVO addSearchMessageToVO(SitesListVO siteListVO, Locale locale, String actionMessageKey, Object[] args) { 
     if (StringUtils.isEmpty(actionMessageKey)) { 
      return siteListVO; 
     } 
     siteListVO.setSearchMessage(messageSource.getMessage(actionMessageKey, args, null, locale)); 
     return siteListVO; 
    } 
    private boolean isSearchActivated(String searchFor) { 
     //return !CollectionUtils.isEmpty(searchFor); 
     return !StringUtils.isEmpty(searchFor); 
    } 
} 

angularjs:

$scope.getContactList = function() { 
     var url = $scope.url; 
     $scope.lastAction = 'list'; 

     $scope.startDialogAjaxRequest(); 

     var config = {params: {page: $scope.pageToGet}}; 

     $http.get(url, config) 

      .success(function (data) { 
//    console.log(data); 
       console.debug(data); 
       $scope.finishAjaxCallOnSuccess(data, null, false); 
      }) 
      .error(function() { 
       $scope.state = 'error'; 
       $scope.displayCreateContactButton = false; 
      }); 
    } 
$scope.populateTable = function (data) { 
      if (data.pagesCount > 0) { 
       $scope.state = 'list'; 

       $scope.page = {source: data.sites, currentPage: $scope.pageToGet, pagesCount: data.pagesCount, totalContacts : data.totalContacts}; 

       if($scope.page.pagesCount <= $scope.page.currentPage){ 
        $scope.pageToGet = $scope.page.pagesCount - 1; 
        $scope.page.currentPage = $scope.page.pagesCount - 1; 
       } 

       $scope.displayCreateContactButton = true; 
       $scope.displaySearchButton = true; 
      } else { 
       $scope.state = 'noresult'; 
       $scope.displayCreateContactButton = true; 

       if(!$scope.searchFor){ 
        $scope.displaySearchButton = false; 
       } 
      } 
      if (data.actionMessage || data.searchMessage) { 
       $scope.displayMessageToUser = $scope.lastAction != 'search'; 

       $scope.page.actionMessage = data.actionMessage; 
       $scope.page.searchMessage = data.searchMessage; 
      } else { 
       $scope.displayMessageToUser = false; 
      } 
    } 

na wiosnę mvc XML mam:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 

      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
       <property name="objectMapper"> 
        <bean class="filter.HibernateAwareObjectMapper" /> 
       </property> 
      </bean> 
      <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/> 
     </list> 
    </property> 
</bean> 

kod klasy HibernateAwareObjectMapper: public class HibernateAwareObjectMapper rozciąga ObjectMapper {

private static final long serialVersionUID = 1L; 

    public HibernateAwareObjectMapper() { 
     registerModule(new Hibernate4Module()); 
    } 

} 

Web XML mam ten filtr:

<filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

; używam następującą zależność:

<dependency> 
    <groupId>org.codehaus.jackson</groupId> 
    <artifactId>jackson-mapper-asl</artifactId> 
    <version>1.9.13</version> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>2.3.3</version> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-annotations</artifactId> 
    <version>2.3.0</version> 
</dependency> 
<dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-hibernate4</artifactId> 
     <version>2.4.0</version> 
</dependency> 

Czy istnieje sposób, aby załadować zbiór Open Session? z góry dziękuję za ponowne odtworzenie

Odpowiedz

0

Jedną z możliwości jest dodanie OpenEntityManagerInViewFilter, który utrzymuje sesję otwartą w widoku.Przykład:

<filter> 
    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
+1

Thank u na powtórce, już próbować ten jeden, trzymając obie filtrem ale mam ten sam błąd, ale kiedy usunąć mój filtr nie może uzyskać dostępu do mojej strony logowania, ponieważ używam zabezpieczenia wiosennego i mam inny błąd, jest poniżej: java.lang.NullPointerException \t w interceptorze.LoginInterceptor.preHandle (LoginInterceptor.java:27) \t at org.springframework. web.servlet.HandlerExecutionChain.applyPreHandle ( – Ahmed

10

rozwiązać, że przez dodanie tej adnotacji @LazyCollection(LazyCollectionOption.FALSE)

//@JsonSerialize(using = CustomListSerializer.class) 
    //@JsonView(Views.Internal.class) 
    //@JsonIgnore 
    @LazyCollection(LazyCollectionOption.FALSE) 
    @OneToMany(mappedBy = "siteesTypeSite", cascade = CascadeType.ALL,fetch = FetchType.LAZY) 
    public Set<Sites> getSitees() { 
     return sitees; 
    }