Hibernate延迟初始化不能与Jackson Mapper一起使用

时间:2015-03-17 07:13:45

标签: json jackson spring-4 hibernate-4.x

我正在使用Spring 4和Hibernate 4.我使用java jpa来使用hibernate。我想懒得加载一些数据。我还配置了Jackson mapper将我的java对象转换为json,反之亦然。但是在将java转换为json时它会抛出异常。我创建了自定义对象映射器,但它仍无法正常工作。

请参阅以下课程,看看我在这里缺少什么

我正在使用注释。 Hibernate配置文件: MvcConfiguration.java

    package com.ampdev.platform.module.common.config;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.ampdev.platform.framework.dataaccess.config.HibernateAwareObjectMapper;
import com.ampdev.platform.framework.rest.security.AuthenticationService;
import com.ampdev.platform.framework.rest.security.AuthenticationServiceDefault;
import com.ampdev.platform.module.user.util.EncryptionUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
@ComponentScan(basePackages = "com.ampdev")
@EnableWebMvc
@EnableTransactionManagement
public class MvcConfiguration extends WebMvcConfigurerAdapter
{

    @Bean
    public ViewResolver getViewResolver()
    {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    @Autowired
    @Bean(name = "authenticationService")
    public AuthenticationService getAuthencticaionService()
    {
        return new AuthenticationServiceDefault();
    }

    @Autowired
    @Bean(name = "passwordEncoder")
    public PasswordEncoder getPasswordEncoder()
    {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    @Bean(name = "encrypyionUtil")
    public EncryptionUtil getEncryptionUtil(PasswordEncoder passwordEncoder)
    {
        return new EncryptionUtil(passwordEncoder);
    }

    @Autowired
    @Bean(name = "objectMapper")
    public ObjectMapper getObjectMapper()
    {
        return new HibernateAwareObjectMapper();
    }

    @Autowired
    @Bean(name = "jsonMessageConverter")
    public MappingJackson2HttpMessageConverter getMessageConvertor()
    {
        return new MappingJackson2HttpMessageConverter();
    }

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MappingJackson2HttpMessageConverter jsonMessageConverter;

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
    {
        jsonMessageConverter.setObjectMapper(objectMapper);
        converters.add(jsonMessageConverter);
    }

}

我创建了一个自定义对象映射器以包含Hibernate4Module HibernateAwareObjectMapper.java

package com.ampdev.platform.framework.dataaccess.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;

public class HibernateAwareObjectMapper extends ObjectMapper
{

    /**
     * 
     */
    private static final long serialVersionUID = -4013528320937607847L;

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

}

这是我在使用延迟加载的Data对象: UserMovieReviewData .java

package com.ampdev.platform.module.movie.review.user.dataobject;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import com.ampdev.platform.module.common.dataobject.PersistedDataObject;
import com.ampdev.platform.module.movie.dataobject.MovieData;
import com.ampdev.platform.module.movie.review.constants.ReviewConstants;
import com.ampdev.platform.module.user.dataobject.UserData;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

@Entity
@Table(name = "movie_review_user")
@JsonInclude(Include.NON_NULL)
public class UserMovieReviewData extends PersistedDataObject
{

    /**
     * 
     */
    private static final long serialVersionUID = -5644749600929596177L;

    @Id
    @GeneratedValue
    @Column(name = "review_id")
    private long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "movie_id")
    private MovieData movieData;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private UserData userData;

    @Column(name = "rating")
    private int rating;

    @Column(name = "title")
    private String title;

    @Column(name = "review")
    private String review;

    @Column(name = "create_date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createDate;

    @Column(name = "update_date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updateDate;

    @Override
    public long getId()
    {
        return id;
    }

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

    public MovieData getMovieData()
    {
        return movieData;
    }

    public void setMovieData(MovieData movieData)
    {
        this.movieData = movieData;
    }

    public UserData getUserData()
    {
        return userData;
    }

    public void setUserData(UserData userData)
    {
        this.userData = userData;
    }

    public int getRating()
    {
        return rating;
    }

    public void setRating(int rating)
    {
        this.rating = rating;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getReview()
    {
        return review;
    }

    public void setReview(String review)
    {
        this.review = review;
    }

    public Date getCreateDate()
    {
        return createDate;
    }

    public void setCreateDate(Date createDate)
    {
        this.createDate = createDate;
    }

    public Date getUpdateDate()
    {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate)
    {
        this.updateDate = updateDate;
    }

}

这是我用作其余资源的我的网络服务资源: ReviewResource.java

package com.ampdev.platform.module.movie.review.resource;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.ampdev.platform.framework.rest.BaseExecutor;
import com.ampdev.platform.framework.rest.RestBaseResource;
import com.ampdev.platform.module.common.constants.URIConstants;
import com.ampdev.platform.module.movie.review.constants.ReviewConstants;
import com.ampdev.platform.module.movie.review.user.dataobject.UserMovieReviewData;

@Controller
@RequestMapping(value = "/ws/movie/review")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ReviewResource extends RestBaseResource
{

    @Autowired
    private BaseExecutor<UserMovieReviewData, UserMovieReviewData> createMovieReviewExecutor;

    @Autowired
    private BaseExecutor<String, List<UserMovieReviewData>> getMovieReviewExecutor;

    @RequestMapping(value = ReviewConstants.ADD, method = RequestMethod.POST)
    public ResponseEntity<UserMovieReviewData> createMovieReview(
        @RequestParam(value = ReviewConstants.TYPE, required = true) String type,
        RequestEntity<UserMovieReviewData> requestEntity)
    {
        createMovieReviewExecutor.setAttribute(ReviewConstants.TYPE, type);
        return performTask(requestEntity, createMovieReviewExecutor);
    }

    @RequestMapping(value = URIConstants.GET_IDS, method = RequestMethod.GET)
    public ResponseEntity<List<UserMovieReviewData>> getReview(
        @RequestParam(value = ReviewConstants.TYPE, required = true) String type, @PathVariable(value = "ids") String reviewIds)
    {
        getMovieReviewExecutor.setAttribute(ReviewConstants.TYPE, type);
        getMovieReviewExecutor.setAttribute(ReviewConstants.REVIEW_IDS, reviewIds);
        return performTask(null, getMovieReviewExecutor);
    }

}

我正在使用spring 4 + hibernate 4.

当我尝试从Rest Web服务调用中获取数据时,我收到以下错误:

I am getting the following error when I am trying to fetch the data from Rest web service:

    org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

根本原因

com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]-&gt;com.ampdev.platform.module.movie.review.user.dataobject.UserMovieReviewData[&quot;movieData&quot;]-&gt;com.ampdev.platform.module.movie.dataobject.MovieData_$$_jvst49f_5[&quot;id&quot;])
    com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
    com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:197)
    com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:187)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:652)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
    com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
    com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
    com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114)
    com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1837)
    org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
    org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

根本原因

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
    org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    com.ampdev.platform.module.movie.dataobject.MovieData_$$_jvst49f_5.getId(MovieData_$$_jvst49f_5.java)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    com.fasterxml.jackson.databind.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:726)
    com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:506)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
    com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
    com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
    com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
    com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114)
    com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1837)
    org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
    org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

1 个答案:

答案 0 :(得分:1)

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

您正在尝试在休眠会话之外访问延迟集合。有几种方法可以解决这个问题,最明显的是访问您要在服务类中序列化的每个集合的size(),这会导致集合被加载,因此可以在会话。

另一种方法是使用FetchType.EAGER注释集合,但这会影响模型的所有使用,这可能不是您想要的。最后,您可以使用OpenSessionInView模式,该模式在请求期间维护一个打开的休眠会话(因此允许您在会话边界之外的地方加载延迟集合)。最后一种选择通常被认为是一种反模式。

相关问题