2014-03-30 97 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()),** 
相關問題