我正在使用AngularJs和Rest服务(RestEasy)构建应用程序,我需要在其中显示产品列表。当用户点击其中一个产品时加载列表后,将加载该产品的详细信息和图像。
当我显示所有产品的列表时,我不想加载与产品相关的集合(即图像),但仅在我需要其中一个产品的详细信息时才出于性能原因,所以我&#39 ; m使用Lazy load。
Hibernate做得很好我可以看到,最初我只加载了一些属性但不加载集合,但是在休息服务中,当杰克逊试图访问该集合来序列化它时,我得到了这个着名的例外:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.domainmodel.Product.Images
当然,此时不再打开Session,并且已经提交了数据库事务。我不想保持会话开放。因此,在网上搜索我看到我们可以告诉杰克逊不要使用注释@JsonIgnore序列化一个属性。 这个注释必须放在Entity(POJO)的属性或getter中,所以基本上,如果我告诉Jackson在序列化为JSON时不要序列化这个集合,它会暂时解决问题但是一旦我需要加载产品该集合因为用户点击了它,它不会序列化该集合,所以我稍后会遇到这个问题。所以我不认为这对我来说是一个解决方案。关于如何解决这种情况的任何想法,建议?我在这里发布实体的代码和其他服务。提前谢谢!!
@Entity
@Table(name = "PRODUCTS")
public class Product implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;
@Column(name = "PATH_TO_IMAGE", nullable = false, insertable = true, updatable = true)
private String pathToImage;
@Column(name="DESCRIPTION",nullable=true, insertable = true, updatable = true)
private String description;
@ManyToOne(optional = false)
@JoinColumn(name = "XID_PRODUCT_TYPE", nullable = false, insertable = false, updatable = false)
private ProductType productType;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "PRODUCT_IMAGE",
joinColumns = {@JoinColumn(name = "XID_PRODUCT", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "XID_IMAGE", referencedColumnName = "ID")})
private List<Image> images;
... getters and setters
}
然后是其他服务的代码:
@Path("/products")
public class ProductsService extends CommonService{
private static final Logger log = Logger.getLogger(ProductsService.class);
@EJB
private ProductsServiceHandler handler;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllProducts(@Context Request request, @Context HttpHeaders httpHeaders)
{
try
{
List<Product> products=handler.findAllProducts();
return Response.ok(products).header(ALLOW_ORIGIN_HEADER, "*").build();
}
catch(Exception e){return Response.status(Status.INTERNAL_SERVER_ERROR).build();}
}
}
按要求完成stackstrace:
2015-02-03 00:35:41,085 ERROR [io.undertow.request] (default task-9) UT005023: Exception handling request to /arenaclub/rest/products: org.jboss.resteasy.spi.UnhandledException: Response is committed, can't handle exception
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:148) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:432) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:376) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs-3.0.8.Final.jar:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.fgonzalez.domainmodel.Product.images, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.fgonzalez.domainmodel.Product["images"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:197) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:187) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:652) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114) [jackson-databind-2.3.2.jar:2.3.2]
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:610) [jackson-databind-2.3.2.jar:2.3.2]
at org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider.writeTo(ResteasyJackson2Provider.java:186) [resteasy-jackson2-provider-3.0.8.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.writeTo(AbstractWriterInterceptorContext.java:129) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.interception.ServerWriterInterceptorContext.writeTo(ServerWriterInterceptorContext.java:62) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:118) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.security.doseta.DigitalSigningInterceptor.aroundWriteTo(DigitalSigningInterceptor.java:143) [resteasy-crypto-3.0.8.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:122) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor.aroundWriteTo(GZIPEncodingInterceptor.java:100) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:122) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:99) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:427) [resteasy-jaxrs-3.0.8.Final.jar:]
... 32 more
答案 0 :(得分:4)
你可以做几件事。
products
并在每个产品上调用setImages(null)
Product
注册两个自定义JSON序列化程序,一个用于序列化图像,另一个用于序列化图像,并根据所调用的服务选择序列化程序。问题是我不确定是否可以使用RestEasy完成,但请查看this thread以获取一些提示答案 1 :(得分:4)
您可以考虑两种可能的选择:
答案 2 :(得分:1)
杰克逊项目的人们开发了一个很好的模块来解决这个问题!
在github上查看: https://github.com/FasterXML/jackson-datatype-hibernate
答案 3 :(得分:0)
您可以在JPA会话中运行Jackson,因此延迟加载将起作用。