如何解决我遇到的“ LazyInitializationException”问题?

时间:2019-02-03 14:45:54

标签: hibernate java-ee lazy-loading marshalling

希望您能够帮助我停止将我的头撞在墙上。

这是我的问题,在许多论坛上进行了大量研究后,我没有找到与我遇到的问题兼容的答案。

我有一个org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.supinfo.suppicture.entity.User.pictures, no session or session was closed似乎是一个已知的异常,但仍然让我发疯...

我尝试强制Eager加载而不是延迟加载,但是仍然存在相同的问题。

这是我的课程:

category.java

@Entity
@Table(name = "category")
@XmlRootElement
public class Category{

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

private String Name;

@OneToMany(mappedBy = "category")
private Collection<Picture> pictures;

(getters and setters)

user.java

@Entity
@Table(name = "user")
@XmlRootElement
public class User {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

private String username;

private String password;

private String firstName;

private String lastName;

private String phoneNumber;

private String postalAddress;

private String email;

@OneToMany(mappedBy = "author")
private Collection<Picture> pictures;

    (getters and setters)

picture.java

@Entity
@Table(name = "picture")
@XmlRootElement
public class Picture {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

private String name;

private String description;

@Column(columnDefinition="longblob")
private byte[] image;

private Date dateOfPublish;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private Category category;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User author;

    (getters and setters)

这是我如何尝试在数据库中检索图片的示例(其中只有唯一一个具有外键的图片)

@Override
public List<Picture> getAllPictures() {
    EntityManager em = emf.createEntityManager();
    try {
        CriteriaQuery<Picture> criteriaQuery = em.getCriteriaBuilder()
            .createQuery(Picture.class);
        criteriaQuery.from(Picture.class);
        return em.createQuery(criteriaQuery).getResultList();
    } finally {
        em.close();
    }
}

最后这样称呼:

@Path("/picture")
public class PictureController {

@GET
@Path("/all") @Produces(MediaType.APPLICATION_JSON)
public List<Picture> getAllPictures(){
    return DaoFactory.getPictureDao().getAllPictures();
}

下面是异常的完整堆栈跟踪:

févr。 2019年3月3日4:38:48 org.hibernate.LazyInitializationException GRAVE:无法延迟初始化角色集合:com.supinfo.suppicture.entity.User.pictures,没有会话或会话被关闭 org.hibernate.LazyInitializationException:无法延迟初始化角色集合:com.supinfo.suppicture.entity.User.pictures,没有会话或会话被关闭     在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)     在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)     在org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)     在org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)     在org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)     在com.sun.xml.internal.bind.v2.runtime.reflect.Lister $ CollectionLister.iterator(Lister.java:266)     在com.sun.xml.internal.bind.v2.runtime.reflect.Lister $ CollectionLister.iterator(Lister.java:253)     在com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:118)     在com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)     在com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:578)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:326)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479)     在com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)     在com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:163)     在com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:145)     在com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:264)     在com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)     在com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1448)     在com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360)     在com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350)     在com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)     在com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)     在com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:725)     在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)     在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)     在org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)     在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)     在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)     在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)     在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)     在org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)     在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)     在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)     在org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)     在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)     在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)     在org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)     在org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:658)     在org.apache.coyote.http11.Http11NioProtocol $ Http11ConnectionHandler.process(Http11NioProtocol.java:222)     在org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1566)     在org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.run(NioEndpoint.java:1523)     在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)     在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:624)     在org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61)     在java.lang.Thread.run(Thread.java:748)

févr。 2019年03月3日4:38:48 org.apache.catalina.core.StandardWrapperValve调用 严重:“ Servlet.service()”注入servlet球衣-servlet一般情况 org.hibernate.LazyInitializationException:无法延迟初始化角色集合:com.supinfo.suppicture.entity.User.pictures,没有会话或会话被关闭     在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)     在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)     在org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)     在org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)     在org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)     在com.sun.xml.internal.bind.v2.runtime.reflect.Lister $ CollectionLister.iterator(Lister.java:266)     在com.sun.xml.internal.bind.v2.runtime.reflect.Lister $ CollectionLister.iterator(Lister.java:253)     在com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:118)     在com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)     在com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:578)     在com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:326)     在com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479)     在com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)     在com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:163)     在com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:145)     在com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:264)     在com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)     在com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1448)     在com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360)     在com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350)     在com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)     在com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)     在com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:725)     在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)     在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)     在org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)     在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)     在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)     在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)     在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)     在org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)     在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)     在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)     在org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)     在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)     在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)     在org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)     在org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:658)     在org.apache.coyote.http11.Http11NioProtocol $ Http11ConnectionHandler.process(Http11NioProtocol.java:222)     在org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1566)     在org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.run(NioEndpoint.java:1523)     在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)     在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:624)     在org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61)     在java.lang.Thread.run(Thread.java:748)

请告诉我您是否需要更多我的代码来帮助我解决问题。 谢谢你。

丢失的开发人员。

4 个答案:

答案 0 :(得分:1)

  • 似乎没有打开会话,也没有事务。您缺少交易的开始和结束。
  • 有两种选择,要么是您自己的经理自己进行交易,要么是某个事务经理在某个容器中进行交易。
  • 非托管环境习惯用法

    EntityManager em = emf.createEntityManager();  EntityTransaction tx = null; 尝试{     tx = em.getTransaction();      tx.begin();

    //做一些工作     ...     在此处输入代码      tx.commit(); } catch(RuntimeException e){     如果(tx!= null && tx.isActive()) tx.rollback();     抛出e; //或显示错误消息 } 最后{     em.close(); }

  • 此处有更多信息:https://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/transactions.html

答案 1 :(得分:1)

让我们分步进行

1)您的jersey网络控制器正在调用dao方法以获取图片列表(无错误)

2)现在您的dao层正在从数据库中获取数据(无错误)

3)值返回到您的Web服务控制器方法(无错误)

4)但是您正在使用自动json转换器将对象数据转换为json。您的图片具有与用户关联的数据。当json转换器尝试获取用户数据时,该值为null,因为您的事务已经结束,从而导致异常。尝试在json转换过程中忽略类别和用户字段,如下所示。

@JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private Category category;

@JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User author;

5)您不应将图片对象直接用于json转换,因为它会导致循环冗余(无限循环)。尝试创建另一个图片包装类来处理这种情况

图片->用户->图片->用户(循环冗余)

为解决此问题,请创建三个包装器类

public class PictureWrapper 
{
    private int id;

    private String name;

    private String description;

    private byte[] image;

    private Date dateOfPublish;

    private CategoryWrapper category;

    private UserWrapper author;
}


public class UserWrapper
{
    private int id;

    private String username;

    private String password;

    private String firstName;

    private String lastName;

    private String phoneNumber;

    private String postalAddress;

    private String email;
}

public class CategoryWrapper
{
    private int id;

    private String Name;
}

然后将getAllPictures方法更改为

public List<PictureWrapper> getAllPictures() 
{
    List<PictureWrapper> resultList = new ArrayList<PictureWrapper>();
    EntityManager em = emf.createEntityManager();
    try 
    {
        CriteriaQuery<Picture> criteriaQuery = em.getCriteriaBuilder().createQuery(Picture.class);
        criteriaQuery.from(Picture.class);
        List<Picture> list =  em.createQuery(criteriaQuery).getResultList();
    if(list != null && list.size() != 0)
    {
        for(Picture picture : list)
        {
            PictureWrapper pictureWrapper = new PictureWrapper();
            //Load data from picture to picture wrapper with user and category
            resultList.add(pictureWrapper);
        }
    }
    } 
    finally 
    {
        em.close();
    }
    return resultList;
}

答案 2 :(得分:0)

您需要使用获取策略OneToMany装饰user.pictures属性category.picturesEAGER

class Category {
    @OneToMany(mappedBy = "category", fetch = FetchType.EAGER)
    Collection<Picture> pictures;
}

class User {
    @OneToMany(mappedBy = "author", fetch = FetchType.EAGER)
    Collection<Picture> pictures;
}

请注意,实际上,您不需要使用ManyToOne获取策略来装饰EAGER属性,因为这被视为默认行为

答案 3 :(得分:0)

感谢Santosh Balaji的把戏;)