2016-04-30 64 views
0

我有3個類(服務層中的UserSrvImpl,dao(存儲庫)層中的MailDaoImpl和UserDaoImpl)。在我的服務層(UserSrvImpl)中,我有一個從MailDaoImpl和UserDaoImpl中調用方法的方法。這2個dao方法必須將對象保存在2個不同的表中。這兩張表有一個OneToOne關係。我的問題是,當第一次插入成功,第二次失敗時,沒有回滾。自一週以來,我一直在努力解決這個問題。我申請了我在谷歌發現的所有解決方案,但仍然沒有成功。你能給我一個幫助嗎? 這裏是我的服務層:@Transactional服務層不回滾Spring MVC +休眠

@Service 
public class UserSrvImpl implements IUserSrv { 
@Autowired 
private IUserDao userDao; 
@Autowired 
private IMailDao mailDao; 

@Override 
@Transactional 
public boolean create(UserDto userDto) { 
    boolean result = false; 
    try { 
     User userToSave = transformDtoToEntity(userDto); 
     MailToken mailToken = createMailTokenForNewUser(userToSave); 

     userToSave.setMailToken(mailToken); 
     if (mailDao.createMailToken(mailToken)) { 
      result = userDao.create(userToSave); 
     } 

    } catch (Exception ex) { 

    } 
    return result; 
} 

的服務調用DAO的方法mailDao.createMailToken和userDao.create。如果第一個成功並且第二個失敗,則數據庫中的第一個表上沒有回滾。 下面是MailDao代碼:

@Repository 
public class MailDao implements IMailDao { 
@Autowired 
private SessionFactory sessionFactory; 

public Session getSession() { 
    Session sess = this.sessionFactory.getCurrentSession(); 
    if (sess == null) { 
     sess = this.sessionFactory.openSession(); 
    } 
    return sess; 
} 

@Override 
public boolean createMailToken(MailToken mailToken) { 
    try { 
     getSession().save(mailToken); 
     return true; 
    } catch (HibernateException ex) { 

    } catch (Exception ex) { 
     // TODO: handle exception 
    } 
    return false; 
} 

下面是一個UserDAOImpl代碼:

@Repository 
public class UserDaoImpl implements IUserDao { 

@Autowired 
private SessionFactory sessionFactory; 

public Session getSession() { 
    Session sess = this.sessionFactory.getCurrentSession(); 
    if (sess == null) { 
     sess = this.sessionFactory.openSession(); 
    } 
    return sess; 
} 

@Override 
public boolean create(User userToSave) { 
    try { 
     getSession().save(userToSave); 
     return true; 
    } catch (HibernateException ex) { 
     ex.printStackTrace(); 

    } catch (Exception ex) { 
     // TODO: handle exception 
    } 

    return false; 
} 

這是我的Spring配置:

<bean id="hibernate5AnnotatedSessionFactory" 
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"></property> 
    <property name="packagesToScan"> 
     <array value-type="java.lang.String"> 
      <value>com.pointsante.dao.domaine</value> 
     </array> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
      <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
      <prop key="hibernate.hbm2ddl.auto">validate</prop> 
     </props> 
    </property> 
</bean> 
<bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"></property> 
</bean> 
<tx:annotation-driven transaction-manager="transactionManager" /> 

請你能告訴我爲什麼@服務層中的方法的事務處理不起作用。謝謝。

+0

我也嘗試刪除所有的try catch塊但問題仍然存在 – Alee

回答

0

你應該使用HibernateTransactionManager而不是DataSourceTransactionManager。的

<bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"></property> 
</bean> 

使用

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

代替了仔細閱讀這裏的服務被調用。如果您從服務類本身內部調用它,則不會使用處理事務管理的代理。

+0

謝謝lumue。用HibernateTransactionManager替換DataSourceTransactionManager解決了這個問題。 – Alee

+0

接下來你的'getSession'方法是危險的。只有'getCurrentSession'不使用'openSession',因爲這會在spring的事務管理範圍之外打開新會話。 –