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
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