не удалось лениво инициализировать коллекцию - PullRequest
2 голосов
/ 21 марта 2012

Я разрабатываю спокойный веб-сервис для моей базы данных. Я использую jpa для извлечения данных из базы данных и весны для архитектуры. Я уже проверил архитектуру с базовыми запросами dao (findById, save ...), и она отлично работает. Затем в реализации dao я добавил новый метод, который в основном выполняет запрос, который тестируется непосредственно на базе данных mysql (и это работает)

public List<PositionHistory> findByFavUserGBuser(Integer favoriteUserId,
        Integer pageNumber, Integer rowsPerPage, String usernameFilter) {
    String queryString="" +
            "SELECT ph.* " +
            "FROM user u, position_history ph, spot s " +
            "WHERE " +
                "ph.date IN (SELECT MAX(ph2.date) FROM position_history ph2 GROUP BY ph2.user_iduser) and " +
                "s.id_spot=ph.spot_idspot and " +
                "u.id_user=ph.user_iduser and  ";

    if (usernameFilter!=null)
        queryString+="u.username like '%:usernameFilter%' and ";

    queryString+="" +
                "ph.user_iduser IN (SELECT ALL fu.user_iduserto FROM favorite_user fu WHERE fu.user_iduserfrom=:favoriteUserId) " +
            "GROUP BY ph.user_iduser " +
            "LIMIT :startLimit,:rowsPerPage";

    Query query = entityManager.createNativeQuery(queryString,PositionHistory.class);
    query.setParameter("favoriteUserId", favoriteUserId);
    query.setParameter("startLimit", pageNumber*rowsPerPage);
    query.setParameter("rowsPerPage", rowsPerPage);

    if (usernameFilter!=null)
        query.setParameter("usernameFilter", usernameFilter);

    return query.getResultList();
}

и затем я создал контроллер для извлечения данных следующим образом:

@Controller
@Transactional
public class MyController {

    @Autowired
    public DaoPositionHistory dph;

    @Transactional
    @RequestMapping(value = "/getData/{id}/", method = RequestMethod.POST)
    @ResponseBody
    public List<PositionHistory> home(@PathVariable int id) {
        List<PositionHistory> resultlist=(List<PositionHistory>) dph.findByNearestPositionGBuser(id, 0, 10, null, null, null);
        return resultlist;
    }
}

но когда я звоню в службу, я получаю следующую ошибку:

ERROR: org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: com.windy.spring.data.User.favoriteSports, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.windy.spring.data.User.favoriteSports, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
    at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
    at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:45)
    at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23)
    at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    at org.codehaus.jackson.map.ser.std.StdContainerSerializers$IndexedListSerializer.serializeContents(StdContainerSerializers.java:122)
    at org.codehaus.jackson.map.ser.std.StdContainerSerializers$IndexedListSerializer.serializeContents(StdContainerSerializers.java:71)
    at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1613)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:142)
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:81)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:94)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:73)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Unknown Source)

Я не могу понять, почему я получаю эту ошибку, если я объявил методы как @transactional? Есть идеи, как решить проблему?

Вот и мой класс пользователя

@XmlRootElement
@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id_user")
    private int idUser;

    private String cellphone;

    private String email;

    @Lob()
    private byte[] foto;

    private String name;

    private String notes;

    private String password;

    private String surname;

    private String username;

    //bi-directional many-to-one association to FavoriteSport
    @OneToMany(mappedBy="user")
    private List<FavoriteSport> favoriteSports;

    //bi-directional many-to-one association to FavoriteSpot
    @OneToMany(mappedBy="user")
    private List<FavoriteSpot> favoriteSpots;

    //bi-directional many-to-one association to FavoriteUser
    @OneToMany(mappedBy="user2")
    private List<FavoriteUser> favoriteUsers;

    //uni-directional many-to-one association to Role
    @ManyToOne
    @JoinColumn(name="role_idrole")
    private Role role;

    //bi-directional many-to-one association to UserAccount
    @OneToMany(mappedBy="user")
    private List<UserAccount> userAccounts;

    public User() {
    }

    public int getIdUser() {
        return this.idUser;
    }

    public void setIdUser(int idUser) {
        this.idUser = idUser;
    }

    public String getCellphone() {
        return this.cellphone;
    }

    public void setCellphone(String cellphone) {
        this.cellphone = cellphone;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public byte[] getFoto() {
        return this.foto;
    }

    public void setFoto(byte[] foto) {
        this.foto = foto;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNotes() {
        return this.notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSurname() {
        return this.surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public List<FavoriteSport> getFavoriteSports() {
        return this.favoriteSports;
    }

    public void setFavoriteSports(List<FavoriteSport> favoriteSports) {
        this.favoriteSports = favoriteSports;
    }

    public List<FavoriteSpot> getFavoriteSpots() {
        return this.favoriteSpots;
    }

    public void setFavoriteSpots(List<FavoriteSpot> favoriteSpots) {
        this.favoriteSpots = favoriteSpots;
    }

    public List<FavoriteUser> getFavoriteUsers() {
        return this.favoriteUsers;
    }

    public void setFavoriteUsers(List<FavoriteUser> favoriteUsers) {
        this.favoriteUsers = favoriteUsers;
    }

    public Role getRole() {
        return this.role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    public List<UserAccount> getUserAccounts() {
        return this.userAccounts;
    }

    public void setUserAccounts(List<UserAccount> userAccounts) {
        this.userAccounts = userAccounts;
    }

}

Ответы [ 3 ]

2 голосов
/ 14 апреля 2012

Я понял это, прочитав другие ответы на ваш вопрос. На всякий случай, если это кому-нибудь нужно, вот пример:

@Override
public OriginServer get(Integer id){
    OriginServer server = (OriginServer) sessionFactory
        .getCurrentSession().get(OriginServer.class, id);
    Hibernate.initialize(server.getPools());
    return server;
}   

В этом примере getPools - это отношение @OneToMany от OriginServer.

1 голос
/ 21 марта 2012

Трассировка стека ясно показывает, что исключение возникает после , когда метод контроллера завершен (и транзакция закрыта).

Так что используйте либо расширенный контекст персистентности (где сеансы живут дольше, чем транзакции)), получите доступ к отложенной коллекции до возврата метода контроллера, измените DAO или отображение, чтобы загружать коллекцию с нетерпением, или не возвращайте объект, содержащий эту коллекцию.

0 голосов
/ 21 марта 2012

Ваша ошибка в том, что вы не инициализируете ассоциации сущностей в своем DAO, а затем преобразователь Джексона пытается преобразовать все ассоциации в вашем возвращаемом объекте в JSON.Поскольку ассоциации не инициализируются, выдается ошибка, поскольку ваш Controller не имеет дескриптора Hibernate Session.

См. Здесь мой ответ, чтобы узнать, как исправить: Spring @ResponseBodyJson Cyclic Reference

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...