我一直在关注本教程: http://www.scribd.com/doc/25244173/Java-Struts-Spring-Hibernate-Tutorial 设置(前面描述)与教程文件一起正常工作,但是当我做了更改 - 删除/更新操作时就不会发生。没有错误或怪癖,它完全无视我!至于检索数据 - 一切都很完美......
几乎所有来自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();
}
}
和spring的 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>
答案 0 :(得分:1)
你的代码看起来好像你没有完全理解Spring依赖注入的概念,因为你的BaseController
做了Spring管理单例和提供依赖的工作。
<强>问题强>
您正在EventController
内自行创建PersonController
和BaseController
个实例,而不是依赖Spring。 Spring无法拦截类实例的手动创建,并通过使用Spring注释@Transactional
注释类来为它们提供所需的事务行为。
<强>解决方案强>
所以,让我们找一个清理这段代码的路径。首先删除类HibernateUtil
,因为它是静态调用,java bean概念和未使用的事务行为的混合,同时它带来了一个没有任何好处的新抽象层。请务必将其从applicationContext.xml
中删除。
现在也从您的BaseController
中移除applicationContext.xml
,然后对其进行重大改写,因为它可以作为PersonController
和EventController
的单身工厂工作,可以正确管理Spring本身就是在这样的环境中。
public abstract class BaseController {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
这种方式BaseController
成为其他扩展类的抽象基类,可以使用提供的Hibernate 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();
}
}
请记住在春季applicationContext.xml
正确注册此课程,以便提供所需的SessionFactory
:
<bean id="eventController" class="com.epa.controller.EventControllerHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
如果从Spring检索类型为EventController
的Spring bean,您将获得一个事务感知代理对象,完全实现委托给EventController
内部实现的业务逻辑的EventControllerHibernate
接口。
记住:应用程序中永远不会出现new EventControllerHibernate()
,因为这不会起作用,因为Spring无法拦截手动创建类实例!以编程方式获取事务感知实例将如下所示:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
EventController eventController = context.getBean("eventController", EventController.class);
答案 1 :(得分:0)
控制器代码不是很优雅。你应该遵循codescape在这里所说的一切。但是,对问题的简单修复如下:您可以返回已注入BaseController()的bean实例,而不是返回新的PersonController()或新的EventController()。这将返回一个代理对象,可以通过spring拦截@Transactional。但是,正如我所说,定义的控制器不是好的代码。