代码之家  ›  专栏  ›  技术社区  ›  Ariel Grabijas

某些请求的LazyInitializationException

  •  0
  • Ariel Grabijas  · 技术社区  · 8 年前

    这可能是重复的,但我已经为这个问题挣扎了几天了。经过几十个教程,书籍,堆栈答案等,我在死胡同。

    这是RESTfull Spring hibernate应用程序

    1. 如何消除lazyinitializationexception和会话问题?我试图在模型类中设置eager fetch,但它对我不起作用,我有事务注释,但仍然是一样的。我打赌它必须在Spring xml配置中以某种方式设置,但不知道如何设置。
    2. 为什么/getAllCountries工作得很好,/GetCountries/id抛出会话错误?我看不出他们之间有什么不同。
    3. 请给我一个基于代码的答案。

    控制器:

        @RestController
        public class CountryController {
    
            @Autowired
            CountryService countryService;
    
            @RequestMapping(value = "/getAllCountries", method = RequestMethod.GET, headers = "Accept=application/json")
            public List<Country> getCountries() {
                List<Country> listOfCountries = countryService.getAllCountries();
                return listOfCountries;
            }
    
            @RequestMapping(value = "/getCountry/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
            public Country getCountryById(@PathVariable int id) {
                return countryService.getCountry(id);
            }
    
            // .....    
        }
    

    DAO:

    @Repository
    public class CountryDAO {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        public void setSessionFactory(SessionFactory sf) {
            this.sessionFactory = sf;
        }
    
        public List<Country> getAllCountries() {
             Session session = this.sessionFactory.getCurrentSession();
             List<Country> countryList = session.createQuery("from Country").list();
        return countryList;
        }
    
        public Country getCountry(int id) {
            Session session = this.sessionFactory.getCurrentSession();
            Country country = (Country) session.load(Country.class, new Integer(id));
            return country;
        }
        // ......
    }
    

    服务:

    @Service("countryService")
    public class CountryService {
    
        @Autowired
        CountryDAO countryDao;
    
        @Transactional
        public List<Country> getAllCountries() {
            return countryDao.getAllCountries();
        }
    
        @Transactional
        public Country getCountry(int id) {
            return countryDao.getCountry(id);
        }
    }
    

    实体:

    @Entity
    @Table(name="COUNTRY")
    public class Country{
    
        @Id
        @Column(name="id")
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        int id;
    
        @Column(name="countryName")
        String countryName; 
    
        @Column(name="population")
        long population;
    
        public Country() {
                super();
        }
        public Country(int i, String countryName,long population) {
            super();
            this.id = i;
            this.countryName = countryName;
            this.population=population;
        }
    
        // getters and setters...
    }
    

    Spring配置xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
        <annotation-driven />
    
        <resources mapping="/resources/**" location="/resources/" />
    
        <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
                destroy-method="close">
                <beans:property name="driverClassName" value="org.postgresql.Driver" />
                <beans:property name="url"
                        value="..." />
                <beans:property name="username" value="postgres" />
                <beans:property name="password" value="..." />
        </beans:bean>
    
        <!-- Hibernate 4 SessionFactory Bean definition -->
        <beans:bean id="hibernate4AnnotatedSessionFactory"
                class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
                <beans:property name="dataSource" ref="dataSource" />
                <beans:property name="annotatedClasses">
                        <beans:list>
                                <beans:value>org.arpit.java2blog.model.Country</beans:value>
                        </beans:list>
                </beans:property>
                <beans:property name="hibernateProperties">
                        <beans:props>
                                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect
                                </beans:prop>
                                <beans:prop key="hibernate.show_sql">true</beans:prop>
                        </beans:props>
                </beans:property>
        </beans:bean>
    
        <context:component-scan base-package="org.arpit.java2blog" />
    
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
                <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
        </beans:bean>
    </beans:beans>
    

    网状物xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        version="3.0">
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
     <servlet-name>spring</servlet-name>
     <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
     </servlet-class>
     <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
     <servlet-name>spring</servlet-name>
     <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    </web-app>
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Baptiste Beauvais    8 年前

    你的问题来自 Session.load() 方法,该方法不返回对象,而是在首次访问非标识符属性时初始化的对象的代理。

    Hibernate文档:

    T荷载(等级, 可序列化id)

    返回具有给定标识符的给定实体类的持久实例,假设

    对你来说,这意味着它在Spring尝试marshall对象时初始化,也就是会话结束时。

    要修复它,您可以添加 @org.hibernate.annotations.Proxy(lazy = false) 在类级别上,使用 Session.get() 而不是 一场加载() 在dao中获取完全加载的对象(取决于成员的延迟策略)。

    或者,当会话仍然类似时,通过调用对象的任何成员(例如调用 List.size() 在集合上强制加载)。