hibernate.LazyInitializationException:懒得初始化一个角色集合

时间:2016-10-28 08:06:12

标签: spring

我已经对此错误进行了研究,但仍无法找到合适的解决方案。这是我的代码:

配置:

package com.ambre.pta.config;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.SessionFactory;
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.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.ambre.pta.dao.MenuDAO;
import com.ambre.pta.dao.MenuDAOImpl;
import com.ambre.pta.dao.RoleDAO;
import com.ambre.pta.dao.RoleDAOImpl;
import com.ambre.pta.dao.UtilisateurDAO;
import com.ambre.pta.dao.UtilisateurDAOImpl;


@Configuration
@ComponentScan("com.ambre.pta")
@EnableTransactionManagement
@PropertySources({
    @PropertySource("classpath:fr/global.properties"),
    @PropertySource("classpath:fr/main.properties"),
    @PropertySource("classpath:fr/admin.properties"),
    @PropertySource("classpath:fr/referentiel.properties")
})
public class ApplicationContextConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() { 
        return new PropertySourcesPlaceholderConfigurer();
    }

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

    @Bean(name = "dataSource")
    public DataSource getDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
        dataSource.setUsername("pta");
        dataSource.setPassword("pta");

        return dataSource;
    }

    @Autowired
    @Bean(name = "sessionFactory")
    public SessionFactory getSessionFactory(DataSource dataSource) {

        LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);

        sessionBuilder.scanPackages("com.ambre.pta.model");

        return sessionBuilder.buildSessionFactory();

    }

    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {

        HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);

        return transactionManager;
    }

    @Autowired
    @Bean(name = "utilisateurDao")
    public UtilisateurDAO getUtilisateurDao(SessionFactory sessionFactory) {
        return new UtilisateurDAOImpl(sessionFactory);
    }

    @Autowired
    @Bean(name = "menuDao")
    public MenuDAO getMenuDao(SessionFactory sessionFactory) {
        return new MenuDAOImpl(sessionFactory);
    }

    @Autowired
    @Bean(name = "roleDao")
    public RoleDAO getRoleDao(SessionFactory sessionFactory) {
        return new RoleDAOImpl(sessionFactory);
    }

}

模特:

    @Entity
    @Table(name = "menu")
    public class Menu {

        @Id
        @SequenceGenerator(name="s_menu", sequenceName="s_menu", allocationSize=1)
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="s_menu")
        private int menu_id;

        private Integer gmnu_code;

        private String menu_lib;

        private Integer menu_ordre;

        private Integer menu_visible;

        private Integer menu_deleted;

        private Integer menu_parent;

        private String menu_controlleur;

        private String menu_navigation;

        @ManyToMany(cascade = CascadeType.ALL)
        @JoinTable(name = "role_menu", joinColumns = { @JoinColumn(name = "menu_id") }, inverseJoinColumns = { @JoinColumn(name = "role_code") })
        private Set<Role> roles = new HashSet<Role>();

        public Menu() {
            super();
        }

        public Menu(Integer gmnu_code, String menu_lib, Integer menu_ordre, Integer menu_visible, Integer menu_deleted, Integer menu_parent, String menu_controlleur, String menu_navigation) {
            super();
            this.gmnu_code = gmnu_code;
            this.menu_lib = menu_lib;
            this.menu_ordre = menu_ordre;
            this.menu_visible = menu_visible;
            this.menu_deleted = menu_deleted;
            this.menu_parent = menu_parent;
            this.menu_controlleur = menu_controlleur;
            this.menu_navigation = menu_navigation;
        }

        public Menu(Integer gmnu_code, String menu_lib, Integer menu_ordre, Integer menu_visible, Integer menu_deleted, Integer menu_parent, String menu_controlleur, String menu_navigation, Set<Role> roles) {
            super();
            this.gmnu_code = gmnu_code;
            this.menu_lib = menu_lib;
            this.menu_ordre = menu_ordre;
            this.menu_visible = menu_visible;
            this.menu_deleted = menu_deleted;
            this.menu_parent = menu_parent;
            this.menu_controlleur = menu_controlleur;
            this.menu_navigation = menu_navigation;
            this.roles = roles;
        }

        // getters and setters....

    }

@Entity
@Table(name = "utilisateur")
public class Utilisateur {

    @Id
    @SequenceGenerator(name="s_utilisateur", sequenceName="s_utilisateur", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="s_utilisateur")
    private int user_code;

    @Formula(value="user_nom || ' ' || user_prenom")
    private String noms;

    private String user_nom;

    private String user_prenom;

    private String user_login;

    private String user_passwd;

    private String user_email;

    private Integer user_deleted;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "role_user", joinColumns = { @JoinColumn(name = "user_code") }, inverseJoinColumns = { @JoinColumn(name = "role_code") })
    private Set<Role> roles = new HashSet<Role>();

    public Utilisateur() {
        super();
    }

    public Utilisateur(String user_nom, String user_prenom, String user_login, String user_passwd, String user_email, Integer user_deleted) {
        super();
        this.user_nom = user_nom;
        this.user_prenom = user_prenom;
        this.user_login = user_login;
        this.user_passwd = user_passwd;
        this.user_email = user_email;
        this.user_deleted = user_deleted;
    }

    public Utilisateur(String noms, String user_nom, String user_prenom, String user_login, String user_passwd, String user_email, Integer user_deleted, Set<Role> roles) {
        super();
        this.noms = noms;
        this.user_nom = user_nom;
        this.user_prenom = user_prenom;
        this.user_login = user_login;
        this.user_passwd = user_passwd;
        this.user_email = user_email;
        this.user_deleted = user_deleted;
        this.roles = roles;
    }

    // getters and setters...

}

@Entity
@Table(name = "role")
public class Role {

    @Id
    private String role_code;

    private String role_lib;

    @ManyToMany(mappedBy = "roles")
    private Set<Menu> menus = new HashSet<Menu>();

    @ManyToMany(mappedBy = "roles")
    private Set<Utilisateur> users = new HashSet<Utilisateur>();

    public Role() {
        super();
    }

    public Role(String role_lib) {
        super();
        this.role_lib = role_lib;
    }

    public Role(String role_lib, Set<Menu> menus) {
        super();
        this.role_lib = role_lib;
        this.menus = menus;
    }

    // getters and setters...

}

现在在我的控制器中,我调用了导致异常的DAO实现:

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ambre.pta.dao.MenuDAO;
import com.ambre.pta.dao.RoleDAO;
import com.ambre.pta.model.DataTablesTO;
import com.ambre.pta.model.Role;

@Controller
@RequestMapping("/adminrole")
public class AdminRole {

    @Autowired
    private Environment env;

    @Autowired
    private MenuDAO menuDao;

    @Autowired
    private RoleDAO roleDao;

    @RequestMapping(value = "/ajaxDataTableListRoles", produces = "application/json")
    @ResponseBody
    public String ajaxListRole(@RequestParam int draw, @RequestParam int start, @RequestParam int length, 
                               @RequestParam("search[value]") String search, @RequestParam("order[0][column]") int triIdx, @RequestParam("order[0][dir]") String ordreTri) 
     {

        List<Role> rolesDataTable = roleDao.list(start, length, search, triIdx, ordreTri);
        List<Role> rolesAll = roleDao.list();
        DataTablesTO<Role> dt = new DataTablesTO<Role>();
        dt.setData(rolesDataTable);
        dt.setDraw(draw);
        if (search == null || search.equals("")) {
            dt.setRecordsTotal(rolesAll.size());
            dt.setRecordsFiltered(rolesAll.size());
        }
        else {
            dt.setRecordsTotal(rolesDataTable.size());
            dt.setRecordsFiltered(roleDao.nbRoleTotalFiltered(search));
        }

        ObjectMapper mapper = new ObjectMapper();

        try {
            return mapper.writeValueAsString(dt);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
            return "";
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return "";
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

}

编辑:

这是异常堆栈:

org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.ambre.pta.model.Role.menus, could not initialize proxy - no Session (through reference chain: com.ambre.pta.model.DataTablesTO["data"]->java.util.ArrayList[0]->com.ambre.pta.model.Role["menus"])
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    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.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.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
    at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
    at com.ambre.pta.controller.AdminRole.ajaxListRole(AdminRole.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:285)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ambre.pta.model.Role.menus, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
    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)
    ... 49 more

那么如何在这种情况下修复延迟加载异常?

编辑:

这里是DAO的实现:

public class RoleDAOImpl implements RoleDAO {

    @Autowired
    private SessionFactory sessionFactory;

    public RoleDAOImpl() {
        super();
    }

    public RoleDAOImpl(SessionFactory sessionFactory) {
        super();
        this.sessionFactory = sessionFactory;
    }

    @Override
    @Transactional
    public List<Role> list() {

        @SuppressWarnings("unchecked")
        List<Role> listRole = (List<Role>) sessionFactory.getCurrentSession()
                                                         .createCriteria(Role.class)
                                                         .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
        return listRole;

    }

    @Override
    @Transactional
    public List<Role> list(int start, int length, String search, int triIdx, String ordreTri) {

        String hql = "select r from Role r";

        if (search != null && !search.equals("")) {

            hql = hql.concat(" where ");

            hql = hql.concat(" lower(r.role_lib) like '%").concat(search.toLowerCase()).concat("%'");

        }

        if (ordreTri.equals("asc")) {

            switch (triIdx) {
                case 0:
                    hql = hql.concat(" order by r.role_lib ");
                    break;
                default:
                    hql = hql.concat(" order by r.role_lib ");
                    break;
            }

        } else {

            switch (triIdx) {
                case 0:
                    hql = hql.concat(" order by r.role_lib desc");
                    break;
                default:
                    hql = hql.concat(" order by r.role_lib desc");
                    break;
            }
        }

        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query = query.setFirstResult(start);
        query = query.setMaxResults(length);

        @SuppressWarnings("unchecked")
        List<Role> listRole = (List<Role>) query.list();

        return listRole;

    }

    @Override
    @Transactional
    public int nbRoleTotalFiltered(String search) {

        String hql = "select r from Role r";

        if (search != null && !search.equals("")) {

            hql = hql.concat(" where ");

            hql = hql.concat(" lower(r.role_lib) like '%").concat(search.toLowerCase()).concat("%'");

        }

        Query query = sessionFactory.getCurrentSession().createQuery(hql);

        @SuppressWarnings("unchecked")
        List<Role> listRole = (List<Role>) query.list();

        return listRole.size();

    }

    @Override
    @Transactional
    public Role get(String role_code) {

        return (Role) sessionFactory.getCurrentSession().get(Role.class, role_code);

    }

    @Override
    @Transactional
    public void saveOrUpdate(Role role) {

        Session sess = sessionFactory.getCurrentSession();
        sess.saveOrUpdate(role);

    }

    @Override
    @Transactional
    public void delete(String role_code) {

        sessionFactory.getCurrentSession().delete((Role) sessionFactory.getCurrentSession().get(Role.class, role_code));

    }

}

2 个答案:

答案 0 :(得分:1)

你需要使用@transactional,LazyInitializationException: failed to lazily initialize a collection of roles, could not initialize proxy - no Session,你需要打开一个事务,让hibernate解析集合的代理,尝试并评论它是否有效

答案 1 :(得分:0)

我使用标准sql createSQLQuery创建了查询,但没有使用Hibernate createQuery创建查询,而dataTable知道索引列!