Java Spring、Hibernate、事务管理、未提交
因此,我尝试使用Spring进行事务管理。最后我的应用程序成功了,但删除不提交。在使用Spring之前,我在DAO中管理事务,我认为在使用Spring之后可以删除此代码。但是现在删除不提交给DB 我的刀:Java Spring、Hibernate、事务管理、未提交,java,spring,hibernate,transactions,Java,Spring,Hibernate,Transactions,因此,我尝试使用Spring进行事务管理。最后我的应用程序成功了,但删除不提交。在使用Spring之前,我在DAO中管理事务,我认为在使用Spring之后可以删除此代码。但是现在删除不提交给DB 我的刀: protected Session getSession() { Session session = sessionFactory.openSession(); ThreadLocalSessionContext.bind(session); return sessio
protected Session getSession() {
Session session = sessionFactory.openSession();
ThreadLocalSessionContext.bind(session);
return session;
}
public void delete(T t) {
Session session = getSession();
// **this approach I used before**
// session.beginTransaction();
// try {
// session.delete(t);
// session.getTransaction().commit();
// } catch (Exception e) {
// session.getTransaction().rollback();
// }
session.delete(t);
}
我的应用程序上下文:
<?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">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://ngs-java-srv.synapse.com:3306/mybase" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- <property name="configLocation" value="hibernate.cfg.xml" /> -->
<property name="packagesToScan" value="todolist.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- dao beans -->
<bean id="userDao"
class="todolist.dao.hibernate.UserDaoImpl">
<constructor-arg>
<value>todolist.entity.User</value>
</constructor-arg>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="itemDao"
class="todolist.dao.hibernate.ItemDaoImpl">
<constructor-arg>
<value>todolist.entity.Item</value>
</constructor-arg>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- service bean -->
<bean id="userService" class="todolist.service.UserServiceImpl">
<property name="userDao" ref="userDao" />
<property name="itemDao" ref="itemDao" />
</bean>
<!-- transaction manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
<!-- <tx:annotation-driven/> -->
<!-- <aop:config>
<aop:pointcut id="serviceMethods"
expression="execution(* todolist.service.UserService.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRES_NEW" />
<tx:method name="deleteItem" no-rollback-for="Exception" />
</tx:attributes>
</tx:advice> -->
<!-- backbeans -->
<bean id="userLogin" class="todolist.jsf.UserLogin"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="userLogged" class="todolist.jsf.UserLogged"
scope="session">
<aop:scoped-proxy />
</bean>
<bean id="userRegister" class="todolist.jsf.UserRegister"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="createItem" class="todolist.jsf.CreateItem"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="todoList" class="todolist.jsf.TodoList"
scope="request">
<property name="userService" ref="userService" />
</bean>
</beans>
org.hibernate.dialogue.mysqldialogue
org.hibernate.cache.internal.NoCacheProvider
假的
更新
todolist.entity.User
todolist.entity.Item
UserServiceImpl类
package todolist.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import todolist.exception.AuthorizationError;
import todolist.exception.DuplicateLoginsException;
import todolist.service.StringToHashTool;
import todolist.dao.ItemDao;
import todolist.dao.UserDao;
import todolist.entity.Item;
import todolist.entity.User;
public class UserServiceImpl implements UserService {
//private static final Logger log = Logger.getLogger(UserServiceImpl.class);
private UserDao userDao;
private ItemDao itemDao;
public void setItemDao(ItemDao itemDao) {
this.itemDao = itemDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isUserExists(String login) {
return (userDao.getUserByLogin(login) != null);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isPasswordCorrect(String login, String password) {
if (isUserExists(login)) {
return userDao.getUserByLogin(login).getPassword()
.equals(StringToHashTool.getHash(password));
} else {
return false;
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public User login(String login, String password) {
if (isPasswordCorrect(login, password)) {
return userDao.getUserByLogin(login);
} else {
throw new AuthorizationError("Incorrect password");
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean register(String login, String password) {
if (isUserExists(login)) {
throw new DuplicateLoginsException("Login " + login + " is already used.");
} else {
User user = new User();
user.setLogin(login);
user.setPassword(StringToHashTool.getHash(password));
userDao.save(user);
return true;
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logout() {
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Item createItem(Long creator_id, Long performer_id,
String description, Date dueDate) {
Item item = new Item();
User user = userDao.getById(creator_id);
item.setCreator(user);
user = userDao.getById(performer_id);
item.setPerformer(user);
item.setDescription(description);
item.setStartDate(new Date());
item.setDueDate(dueDate);
itemDao.save(item);
return item;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void deleteItem(Long item_id) {
Item item = itemDao.getById(item_id);
itemDao.delete(item);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public List<Item> getUserItems(String login) {
User user = userDao.getUserByLogin(login);
return itemDao.getItemsByPerformer(user.getId());
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public List<User> getUsers() {
return userDao.getUsers();
}
}
包todolist.service;
导入java.util.ArrayList;
导入java.util.Date;
导入java.util.List;
导入org.apache.log4j.Logger;
导入org.springframework.transaction.annotation.Propagation;
导入org.springframework.transaction.annotation.Transactional;
导入todolist.exception.AuthorizationError;
导入todolist.exception.DuplicateLoginsException;
导入todolist.service.StringToHashTool;
导入todolist.dao.ItemDao;
导入todolist.dao.UserDao;
导入todolist.entity.Item;
导入todolist.entity.User;
公共类UserServiceImpl实现UserService{
//私有静态最终记录器log=Logger.getLogger(userserviceinpl.class);
私有UserDao UserDao;
私有ItemDao ItemDao;
公共void setItemDao(ItemDao ItemDao){
this.itemDao=itemDao;
}
公共void setUserDao(UserDao UserDao){
this.userDao=userDao;
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共布尔值isUserExists(字符串登录){
返回(userDao.getUserByLogin(login)!=null);
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共布尔值isPasswordCorrect(字符串登录,字符串密码){
如果(isUserExists(登录)){
返回userDao.getUserByLogin(login.getPassword())
.equals(StringToHashTool.getHash(密码));
}否则{
返回false;
}
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共用户登录(字符串登录、字符串密码){
if(isPasswordCorrect(登录,密码)){
返回userDao.getUserByLogin(login);
}否则{
抛出新的授权错误(“不正确的密码”);
}
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共布尔寄存器(字符串登录,字符串密码){
如果(isUserExists(登录)){
抛出新的DuplicateLoginsException(“Login”+Login+”已被使用。”);
}否则{
用户=新用户();
user.setLogin(login);
user.setPassword(StringToHashTool.getHash(password));
保存(用户);
返回true;
}
}
@凌驾
@事务性(传播=传播。需要\u新建)
公开作废注销(){
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共项createItem(长创建者id、长执行者id、,
字符串说明,日期(日期){
项目=新项目();
User=userDao.getById(创建者id);
item.setCreator(用户);
user=userDao.getById(执行者id);
item.setPerformer(用户);
项目说明(说明);
item.setStartDate(新日期());
项目。设置截止日期(截止日期);
itemDao.save(item);
退货项目;
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共无效删除项(长项\u id){
Item Item=itemDao.getById(Item\u id);
itemDao.delete(item);
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共列表getUserItems(字符串登录){
User=userDao.getUserByLogin(登录);
返回itemDao.getItemsByPerformer(user.getId());
}
@凌驾
@事务性(传播=传播。需要\u新建)
公共列表getUsers(){
返回userDao.getUsers();
}
}
第一步:
将此更改为:
<aop:pointcut
id="serviceMethods"
expression="todolist.service.UserServiceImpl.delete()"
/>
查看delete是否开始提交。我只是想确保你把所有的打字错误都清除掉。如果此显式配置失败,则配置肯定有问题。在DAO中使用
getCurrentSession
而不是openSession
,因此getSession方法如下所示:
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
您正在创建一个使用不同数据库连接的新会话,因此为该服务设置的事务不适用
同样,当您配置DAO时,DAO将有一个默认范围singleton;将实体作为构造函数参数传递没有意义。单例不应该具有特定于某个事务的实例状态。我成功地使用了Spring HibernateTransactionManager对象和注释驱动配置。在我的应用程序上下文中,我只声明以下两个bean:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="session_factory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
将事务注释移动到尽可能靠近视图的位置(在MVC中)很重要。原因是1)性能和2)原子事务。如果调用UserService的调用在单个函数调用中调用isUserExists、isPasswordCorrect和login方法,则您希望这些方法在单个事务中执行。为此,请从UserServiceImpl中删除@Transactional注释并将其移动到调用类。这确保了所有三个方法调用都使用一个事务。对于原子执行,这同样有效。想想经典的银行转账例子。如果在UserService上有两个单独的事务,则前两个方法调用可能成功,最后一个失败。
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="session_factory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
public class UserServiceImpl implements UserService {
private final UserDao userDao;
private final ItemDao itemDao;
public UserServiceImpl(UserDao userDao, ItemDao itemDao) {
this.userDao = userDao;
this.itemDao = itemDao;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isUserExists(String login) {
return (userDao.getUserByLogin(login) != null);
}
...