2014-03-30 100 views
0

我浪费了太多的时间在这,它的时间来问这里,谢谢。Hibernate懒惰初始化例外与@Transactional

Frameworkds:4用SpringMVC + Hibernate的3.6.0

我期待什么:显示一个POJO(一对多)对象JSP页面

我的配置

上1.applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd"> 

    <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource"> 
     <property name="driver" value="com.mysql.jdbc.Driver"/> 
     <property name="driverUrl" value="jdbc:mysql://localhost:3306/xxx"/> 
     <property name="user" value="-"/> 
     <property name="password" value="-"/> 
     <property name="maximumConnectionCount" value="10"/> 
     <property name="minimumConnectionCount" value="5"/> 
    </bean> 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="packagesToScan" value="com.test.pojo"/> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
       <!-- auto generate table --> 
      </props> 
     </property> 
    </bean> 
</beans> 

2.dispatcher-servlet.xml中

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:mvc="http://www.springframework.org/schema/mvc" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 

     xmlns:task="http://www.springframework.org/schema/task" 

     xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans.xsd 
          http://www.springframework.org/schema/mvc 
          http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.1.xsd 
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 

          http://www.springframework.org/schema/task 
          http://www.springframework.org/schema/task/spring-task-3.0.xsd"> 



    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <task:annotation-driven /> 

    <mvc:annotation-driven /> 

    <context:component-scan base-package="com.test.module" /> 

    <!--HandlerMapping--> 
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> 

    <!--HandlerAdapter--> 
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> 

    <!--ViewResolver --> 
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> 
     <property name="prefix" value="/views/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 

</beans> 

3.Controller

@Transactional 
@Controller 
public class TESTS { 

    @Resource(name="sessionFactory") 
    private SessionFactory sessionFactory; 

    @RequestMapping("/hello") 
    public ModelAndView test(){ 
     ModelAndView mv = new ModelAndView(); 
     mv.setViewName("/hello"); 
     mv.addObject("master", (Master) sessionFactory.getCurrentSession().createQuery("from Master where master_id = 1").uniqueResult()); 
     return mv; 
    } 
} 

4.Pojos

public class Master { 
    @Id 
    @GeneratedValue 
    private Integer master_id; 
    private String master_name; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy="master", cascade = CascadeType.ALL,orphanRemoval=true) 
    private List<Pet> pets; 
} 

public class Pet { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "master_id", nullable = false) 
    private Master master; 
} 

即使我把@Transnational注释提前@Controller,我仍然可以” t获取宠物的信息,总是得到一个异常,表示'未能懒惰地初始化一个角色集合:com.test.pojo.Master.pets,没有会话或会话被关闭'

请指教谢谢!

回答

1

异常说明了一切。您正尝试从JSP中访问延迟加载的集合。当您执行JSP时,控制器的事务方法已返回,并且事务及其关联的会话已关闭。所以Hibernate不能加载集合了。

确保从控制器加载集合,或使用OpenSessionInViewFilter或OpenSessionInViewInterceptor。

  • 呼叫master.getPets().size()(或集合的任何其它方法),或
  • 呼叫Hibernate.initialize(master.getPets()),或
  • 负载主站和它的宠物在单个:

    来自控制器加载集合查询:select m from Master m left join fetch m.pets where...

请注意,您当前的代码使用查询时,它应该简单地使用session.get()来获得一个Mas通过ID。

0
You have put **"fetch = FetchType.LAZY"**, while mapping pets, so hibernate will just load the proxies for Object "Pets" . 
Either yo can make it to **"fetch = FetchType.EAGER"**, with only drawback that Hibernate will always load "Pets object" along with master object even if you do not need. 
So better way is to intialize using Hibernate 

**Hibernate.initialize(master.getPets()),** 
相关问题