[英]Spring Session Management Issue
我在演示应用程序中使用Hibernate + Spring + Jsf,我希望Spring处理事务管理,所以我在application-context.xml文件中创建了这些条目。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Beans Declaration -->
<bean id="User" class="com.otv.model.User"/>
<!-- User Service Declaration -->
<bean id="UserService" class="com.otv.user.service.UserService">
<property name="userDAO" ref="UserDAO" />
</bean>
<!-- User DAO Declaration -->
<bean id="UserDAO" class="com.otv.user.dao.UserDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<!-- Data Source Declaration -->
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="user" value="postgres" />
<property name="password" value="hariom" />
<property name="maxPoolSize" value="10" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- Session Factory Declaration -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>com.otv.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.autocommit">false</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Transaction Manager is defined -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
</beans>
和UserService.java类
package com.otv.user.service;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.otv.model.User;
import com.otv.user.dao.IUserDAO;
/**
*
* User Service
*
* @author onlinetechvision.com
* @since 25 Mar 2012
* @version 1.0.0
*
*/
@Transactional(readOnly = true)
public class UserService implements IUserService {
// UserDAO is injected...
IUserDAO userDAO;
/**
* Add User
*
* @param User user
*/
@Transactional(readOnly = false)
public void addUser(User user) {
getUserDAO().addUser(user);
}
/**
* Delete User
*
* @param User user
*/
@Transactional(readOnly = false)
public void deleteUser(User user) {
getUserDAO().deleteUser(user);
}
/**
* Update User
*
* @param User user
*/
@Transactional(readOnly = false)
public void updateUser(User user) {
getUserDAO().updateUser(user);
}
/**
* Get User
*
* @param int User Id
*/
public User getUserById(int id) {
return getUserDAO().getUserById(id);
}
/**
* Get User List
*
*/
public List<User> getUsers() {
return getUserDAO().getUsers();
}
/**
* Get User DAO
*
* @return IUserDAO - User DAO
*/
public IUserDAO getUserDAO() {
return userDAO;
}
/**
* Set User DAO
*
* @param IUserDAO - User DAO
*/
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
}
现在我在做豆子
@ManagedProperty(value="#{UserService}")
IUserService userService;
*/
public IUserService getUserService() {
return userService;
}
/**
* Set User Service
*
* @param IUserService - User Service
*/
public void setUserService(IUserService userService) {
this.userService = userService;
}
public String addUser() {
try {
User user = new User();
user.setId(getId());
user.setName(getName());
user.setSurname(getSurname());
userService = getUserService();
userService.addUser(user);
userService.deleteUser(null);
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
在此代码中, userService.deleteUser(null);
我正在强行处理异常,但仍然将数据保存在数据库中吗? 如果出现异常而不回滚数据,为什么事务管理不能处理这种情况?
UserDAO类别
package com.otv.user.dao;
import java.util.List;
import com.otv.model.User;
import org.hibernate.SessionFactory;
public class UserDAO implements IUserDAO {
private SessionFactory sessionFactory;
/**
* Get Hibernate Session Factory
*
* @return SessionFactory - Hibernate Session Factory
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* Set Hibernate Session Factory
*
* @param SessionFactory - Hibernate Session Factory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Add User
*
* @param User user
*/
public void addUser(User user) {
getSessionFactory().getCurrentSession().save(user);
}
/**
* Delete User
*
* @param User user
*/
public void deleteUser(User user) {
getSessionFactory().getCurrentSession().delete(user);
}
/**
* Update User
*
* @param User user
*/
public void updateUser(User user) {
getSessionFactory().getCurrentSession().update(user);
}
/**
* Get User
*
* @param int User Id
* @return User
*/
public User getUserById(int id) {
List list = getSessionFactory().getCurrentSession()
.createQuery("from User where id=?")
.setParameter(0, id).list();
return (User)list.get(0);
}
/**
* Get User List
*
* @return List - User list
*/
public List<User> getUsers() {
List list = getSessionFactory().getCurrentSession().createQuery("from User").list();
return list;
}
}
似乎事务边界是UserService类上的每个方法。 当您说userService.addUser(user)
,这是一个事务的开始和完成。 因此,当您说userService.deleteUser(null)
这是另一笔交易-尽管失败,但由于已提交,因此前一笔交易不会回滚。
如果您想在一个事务中完成所有操作,请使用@Transactional注释您的addUser()(或包含在程序化事务中)
方法上的@Transactional
注释定义了事务的边界(除非其他人已经在运行“外部事务”)。 以同样的方式@Transactional
类的注释,使所有单调用该类交易的实例(公共)的方法,但不会 连续的方法调用同一个实例在一个事务中被包裹起来。 相反,每个方法调用都在其自己的事务中运行,并且如果该方法正常返回,则将提交事务。 (默认情况下,即使抛出了检查到的异常,它甚至会被提交,尽管您可以使用rollbackFor
和noRollbackFor
参数来更改它。)
因此,在您的情况下,您有两项交易; 一个用于此调用:
userService.addUser(user);
它成功创建了一个用户,并在对addUser
的调用完成时提交,第二个则完成:
userService.deleteUser(null);
当NullPointerException从方法调用中引发时,它会回滚。 (我猜您在这里得到了NPE,并且由于这是RuntimeExcepotion的子类,因此会引起回滚。)
如果要在单个事务中同时包含两个语句,则需要在更高级别上进行事务。 此处的'@ Transactional`注释不会受到伤害,但它们不是您想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.