0

我一直在關注本教程: http://www.scribd.com/doc/25244173/Java-Struts-Spring-Hibernate-Tutorial 設置(前面描述)與教程文件工作正常,但是當我更改 - 刪除/更新操作不會發生。沒有錯誤或怪癖,它完全忽略了我!至於檢索數據 - 一切都很完美..休眠和彈簧加載操作做trich,更新/刪除操作不要

幾乎所有來自tut的文件都是相同的,有這些差異;本教程使用一個服務文件:

Services.java

package services; 

import org.springframework.transaction.annotation.Transactional; 
import org.hibernate.SessionFactory; 
import org.hibernate.Session; 
import data.*; 
import java.util.List; 

// This class is the business services tier in the application. 
// @Transactional is needed so that a Hibernate transaction is set up, 
// otherwise updates won't have an affect 
@Transactional 
public class Services { 
    // So Spring can inject the session factory 
    SessionFactory sessionFactory; 
    public void setSessionFactory(SessionFactory value) { 
     sessionFactory = value; 
    } 

    // Shortcut for sessionFactory.getCurrentSession() 
    public Session sess() { 
     return sessionFactory.getCurrentSession(); 
    } 

    public Event getEventById(long id) { 
     return (Event) sess().load(Event.class, id); 
    } 

    public Person getPersonById(long id) { 
     return (Person) sess().load(Person.class, id); 
    } 

    public void deleteEventById(long id) { 
     sess().delete(getEventById(id)); 
    } 

    public void deletePersonById(long id) { 
     sess().delete(getPersonById(id)); 
    } 

    public void createEvent(String name) { 
     Event theEvent = new Event(); 
     theEvent.setName(name); 
     sess().save(theEvent); 
    } 

    public void createPerson(String name) { 
     Person p = new Person(); 
     p.setName(name); 
     sess().save(p); 
    } 

    @SuppressWarnings("unchecked") 
    public List getEvents() { 
     return sess().createQuery("from Event").list(); 
    } 

    @SuppressWarnings("unchecked") 
    public List getPeople() { 
     return sess().createQuery("from Person").list(); 
    } 

    public void removePersonFromEvent(int personId, int eventId) { 
     getEventById(eventId).getPeople().remove(getPersonById(personId)); 
    } 

    public void addPersonToEvent(int personId, int eventId) { 
     getEventById(eventId).getPeople().add(getPersonById(personId)); 
    } 
} 

,我曾嘗試使用父控制器和靜態調用的HibernateUtil的文件分開: HibernateUtil.java

package com.epa.util; 

import org.hibernate.SessionFactory; 
import org.springframework.transaction.annotation.Transactional; 
@Transactional 
public class HibernateUtil { 

    // So Spring can inject the session factory 
    static SessionFactory sessionFactory; 
    public void setSessionFactory(SessionFactory value) { 
     sessionFactory = value; 
    } 

    // Shortcut for sessionFactory.getCurrentSession() 
    public static SessionFactory getSessionFactory() { 
     return sessionFactory; 
    } 
} 

BaseController.java

package com.epa.controller.base; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.springframework.transaction.annotation.Transactional; 

import com.epa.controller.EventController; 
import com.epa.controller.PersonController; 
import com.epa.util.HibernateUtil; 

@Transactional 
public class BaseController { 

    protected SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); 
    // Shortcut for sessionFactory.getCurrentSession() 
    public Session sess() { 
     return sessionFactory.getCurrentSession(); 
    } 

    private PersonController personController = null; 
    private EventController eventController = null; 

    public PersonController getPersonController() { 
     if (this.personController == null) { 
      this.personController = new PersonController(); 
     } 
     return personController; 
    } 

    public EventController getEventController() { 
     if (this.eventController == null) { 
      this.eventController = new EventController(); 
     } 
     return eventController; 
    } 
} 

EventController.java

package com.epa.controller; 

import java.util.List; 

import org.springframework.transaction.annotation.Transactional; 

import com.epa.controller.base.BaseController; 
import com.epa.model.Event; 

@Transactional 
public class EventController extends BaseController { 

    public Event getEventById(long id) { 
     return (Event) sess().load(Event.class, id); 
    } 

    public void deleteEventById(long id) { 
     sess().delete(getEventById(id)); 
    } 

    public void createEvent(String name) { 
     Event theEvent = new Event(); 
     theEvent.setName(name); 
     sess().save(theEvent); 
    } 

    @SuppressWarnings("unchecked") 
    public List getEvents() { 
     return sess().createQuery("from Event").list(); 
    } 

} 

和春天的的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" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    <!-- The singleton hibernate session factory --> 
    <bean id="sessionFactory" scope="singleton" 
     class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
    </bean> 

    <!-- Spring's hibernate transaction manager, in charge of making hibernate sessions/txns --> 
    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <!-- So classes/functions with @Transactional get a hibernate txn --> 
    <tx:annotation-driven /> 

    <!-- Inject my business services class to the actions 
    <bean id="services" class="com.epa.services.Services" scope="singleton"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean>--> 

    <!-- Inject my business services class to the actions --> 
    <bean id="hibernateUtil" class="com.epa.util.HibernateUtil" scope="singleton"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <bean id="baseController" class="com.epa.controller.base.BaseController" scope="singleton" /> 

</beans> 

回答

1

你的代碼看起來,如果你沒有完全理解的Spring依賴注入的概念,因爲你BaseController確實是Spring管理單例和提供依賴關係的工作。

問題

您正在創建自己EventControllerPersonController情況下,BaseController內,而不是依賴於春季。 Spring不能攔截類實例的手動創建,並通過使用Spring註釋@Transactional註釋類來爲它們提供所需的事務行爲。

解決方案

所以,讓我們找到清理這段代碼了道路。首先刪除類HibernateUtil,因爲它是靜態調用,java bean概念和未使用的事務行爲的混合體,同時它帶來了沒有任何好處的新抽象層。請記得從applicationContext.xml中刪除它。

現在從您的applicationContext.xml刪除BaseController也並給它一個重大改寫,因爲它可以作爲一個Singleton,廠家爲PersonControllerEventController這將由Spring本身在這樣的環境中正常管理。

public abstract class BaseController { 

    private SessionFactory sessionFactory; 

    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 

    protected Session getCurrentSession() { 
     return sessionFactory.getCurrentSession(); 
    } 

} 

這樣BaseController變成用於其他擴展類,其中可利用所提供的休眠Session對象的抽象基類。現在讓我們爲您的EventController創建一個漂亮的界面。

public interface EventController { 

    Event getEventById(long id); 

    void deleteEventById(long id); 

    Event createEvent(String name); 

    List getEvents(); 

} 

接下來,我們需要對Hibernate上述接口的實現,從而讓我們稱這個新類EventControllerHibernate利用較早創建BaseController實施。

public class EventControllerHibernate extends BaseController implements EventController { 

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 
    public Event getEventById(long id) { 
     return (Event) getCurrentSession().get(Event.class, id); 
    } 

    @Transactional(propagation = Propagation.REQUIRED) 
    public void deleteEventById(long id) { 
     getCurrentSession().delete(getEventById(id)); 
    } 

    @Transactional(propagation = Propagation.REQUIRED) 
    public Event createEvent(String name) { 
     return (Event) getCurrentSession().save(new Event(name)); 
    } 

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 
    @SuppressWarnings("unchecked") 
    public List getEvents() { 
     return getCurrentSession().createQuery("from Event").list(); 
    } 

} 

記住使得所需的SessionFactory提供給在Spring applicationContext.xml正確註冊這個類,太:

<bean id="eventController" class="com.epa.controller.EventControllerHibernate"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

如果從春檢索EventController類型的春豆你會得到一個事務感知代理對象,完全實現您的EventController接口,委託給在EventControllerHibernate內部實現的業務邏輯。

記住:一個new EventControllerHibernate()應該永遠不會發生在,因爲這您的應用程序不會做的伎倆,因爲春天無法攔截手動創建一個類的實例!以編程方式獲取交易感知實例將如下所示:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 
EventController eventController = context.getBean("eventController", EventController.class); 
0

控制器代碼不是很優雅。你應該遵循codescape在這裏所說的一切。然而,對問題的簡單解決方法如下:不是返回一個新的PersonController()或新的EventController(),而是返回一個已注入到BaseController()中的相同的bean實例。這將返回一個代理對象,其中@Transactional可以在春天被攔截。但是,正如我所說的,定義的控制器不是很好的代碼。