2012-05-16 89 views
2

所以,我嘗試使用Spring進行事務管理。最後我的應用程序已經工作,但刪除不提交。在使用Spring之前,我在DAO中管理事務,並且在我可以刪除這些代碼之後我認爲這是事實。但現在刪除不要提交給數據庫。Spring,Hibernate,事務管理,沒有提交

吾道:

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); 
    } 

我的applicationContext:

<?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> 

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(); 
    } 
} 

回答

2
<aop:pointcut 
    id="serviceMethods" 
    expression="execution(*todolist.service.UserService.*(..))" 
/> 

第一步:

更改爲:

<aop:pointcut 
    id="serviceMethods" 
    expression="todolist.service.UserServiceImpl.delete()" 
/> 

查看是否刪除的開始提交。我只是想確保你清除任何錯別字和你有什麼。如果這個明確的配置失敗,那麼配置一定有問題。

+0

這是錯字,我試過ti隱藏我的域名: - [ –

+0

你能提供全班嗎?什麼是UserService的一個接口? – nsfyn55

+0

請參閱有問題的其他代碼。 –

0

嘗試在你的DAO使用getCurrentSession代替openSession,這樣的getSession方法是這樣的:

protected Session getSession() { 
    return sessionFactory.getCurrentSession(); 
} 

我的猜測是,你正在創建一個使用不同的數據庫連接,使交易成立了一個新的會話該服務不適用。

同樣當你有他們配置的DAO將有一個單身的默認範圍,所以在構造函數參數傳遞實體沒有任何意義。

+0

感謝您的幫助。當我改變我的getSession()時,我得到了下一個異常:在UserDaoImpl的過程中沒有活動事務時,createCriteria無效public User getUserByLogin(String login){session} = getSession(); System.out.println(「Session is null:」+(session == null)); \t Criteria criteria = session.createCriteria(User.class); \t criteria.add(Restrictions.eq(「login」,login)); \t return(User)criteria.uniqueResult(); } –

+0

當我改變了我的getSession(),我得到了下一個異常:在UserDaoImpl的過程中沒有活動事務時,createCriteria無效public User getUserByLogin(String login){Session session = getSession(); Criteria criteria = session.createCriteria(User.class); –

+0

我刪除了線程從我的configuterion和現在的應用程序明星好,但是當我嘗試打開頁面,必須加載一些集合,get可以「不初始化代理 - 沒有會話」 –

0

我已經使用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" /> 

然後在我的業務層,你的UserServiceImpl例如:

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); 
} 

... 

給您移動的交易是非常重要的註解接近儘可能查看(在MVC中)。原因是1)性能和2)原子交易。如果調用UserService的調用在單個函數調用中調用isUserExists,isPasswordCorrect和login方法,則您希望這些調用在單個事務中執行。爲此,請從UserServiceImpl中移除@Transactional註釋並將其移至調用類。這確保了所有三個方法調用都使用單個事務。對於原子執行,這也適用。想想經典銀行匯款的例子。如果在UserService上有兩個獨立的事務,則前兩個方法調用可以成功,最後一個失敗。這兩個事務將被提交,因爲它們處於單獨的事務塊中,這會使數據庫處於不一致的狀態。當然,原子事務主要與寫數據的事務有關。

此外,不要將事務性註釋添加到接口,並將它們保留在實現中。

然後在我的DAO中,我只需要做一個sessionFactory.getCurrentSession()並從那裏開始。 getCurrentSession()是線程安全的,但保持它對你的DAO是私有的。

+0

謝謝你的回答。我提出改變。但我的刪除仍然沒有提交。寫數據很好。在我的JSF bean中,我刪除循環中的項目,可能是這個原因嗎? –

+0

發佈您的代碼和彈簧配置 – user1351763

+0

我按照您的要求在回答中發佈新代碼。 –

相關問題