Hibernate和Spring-load操作执行trich,更新/删除操作不';T
我一直在学习本教程: 设置(前面描述的)可以很好地处理教程文件,但是当我做了更改后,删除/更新操作就不会发生了。没有错误或怪癖,它完全忽略了我!至于检索数据,一切都很完美 几乎所有来自图坦卡蒙的文件都是相同的,但有这些不同之处;本教程使用服务文件: Services.javaHibernate和Spring-load操作执行trich,更新/删除操作不';T,hibernate,spring,dependency-injection,sessionfactory,spring-transactions,Hibernate,Spring,Dependency Injection,Sessionfactory,Spring Transactions,我一直在学习本教程: 设置(前面描述的)可以很好地处理教程文件,但是当我做了更改后,删除/更新操作就不会发生了。没有错误或怪癖,它完全忽略了我!至于检索数据,一切都很完美 几乎所有来自图坦卡蒙的文件都是相同的,但有这些不同之处;本教程使用服务文件: Services.java package services; import org.springframework.transaction.annotation.Transactional; import org.hibernate.Sessio
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));
}
}
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;
}
}
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;
}
}
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();
}
}
我尝试使用父控制器和对HibernateUtil的静态调用来分离文件:
HibernateUtil.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));
}
}
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;
}
}
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;
}
}
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();
}
}
BaseController.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));
}
}
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;
}
}
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;
}
}
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();
}
}
EventController.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));
}
}
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;
}
}
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;
}
}
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>
您的代码看起来好像没有完全理解Spring依赖项注入的概念,因为您的
BaseController
执行Spring管理单例和提供依赖项的工作
问题
您正在BaseController
中自己创建EventController
和PersonController
实例,而不是依赖Spring。Spring无法拦截类实例的手动创建,并通过使用Spring注释@transactional
来为它们提供此处所需的事务行为
解决方案
因此,让我们找到一条路径来清理这段代码。首先删除HibernateUtil类,因为它是静态调用、javabean概念和未使用的事务行为的混合体,同时它带来了一个新的抽象层,没有任何好处。请记住也将其从applicationContext.xml
中删除
现在从applicationContext.xml
中删除BaseController
,并对其进行重大重写,因为它是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
就成为其他扩展类的抽象基类,这些扩展类可以利用提供的HibernateSession
对象。现在,让我们为您的EventController
创建一个漂亮的界面
public interface EventController {
Event getEventById(long id);
void deleteEventById(long id);
Event createEvent(String name);
List getEvents();
}
接下来,我们需要为Hibernate实现上述接口,因此让我们使用先前创建的BaseController
实现调用新类EventControllerHibernate
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();
}
}
请记住在SpringapplicationContext.xml
中正确注册此类,以便也提供所需的SessionFactory
:
<bean id="eventController" class="com.epa.controller.EventControllerHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
控制器代码不是很优雅。您应该遵循codescape在这里所说的一切。然而,解决这个问题的一个简单方法是:不返回新的PersonController()或新的EventController(),而是返回已注入BaseController()的相同bean实例。这将返回一个代理对象,spring可以在其上拦截@Transactional。但是,正如我所说的,由定义的控制器不是好代码