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可以在春天被拦截。但是,正如我所说的,定义的控制器不是很好的代码。