服务层上的@Transactional 不回滚Spring MVC+Hibernate
@Transactional on service layer not rolling back Spring MVC+Hibernate
我有 3 个 类(服务层中的 UserSrvImpl,dao(存储库)层中的 MailDaoImpl 和 UserDaoImpl)。在我的服务层 (UserSrvImpl) 中,我有一个方法调用 MailDaoImpl 的方法和 UserDaoImpl 的方法。这 2 个 dao 方法必须将对象保存在 2 个不同的 table 中。这 2 table 具有 OneToOne 关系。我的问题是当第一次插入成功而第二次插入失败时,没有回滚。一个星期以来,我一直在努力解决这个问题。我应用了我在 google 中找到的所有解决方案,但仍然没有成功。你能帮我个忙吗?
这是我的服务层:
@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。如果第一次成功而第二次失败,则数据库中的第一个 table 不会回滚。
下面是 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" />
请你告诉我为什么服务层方法上的@Transactional 不起作用。谢谢。
您可能应该使用 HibernateTransactionManager 而不是 DataSourceTransactionManager。
使用
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
而不是
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
还要检查调用服务的位置。如果您从服务 class 本身调用它,将不会使用处理事务管理的代理。
我有 3 个 类(服务层中的 UserSrvImpl,dao(存储库)层中的 MailDaoImpl 和 UserDaoImpl)。在我的服务层 (UserSrvImpl) 中,我有一个方法调用 MailDaoImpl 的方法和 UserDaoImpl 的方法。这 2 个 dao 方法必须将对象保存在 2 个不同的 table 中。这 2 table 具有 OneToOne 关系。我的问题是当第一次插入成功而第二次插入失败时,没有回滚。一个星期以来,我一直在努力解决这个问题。我应用了我在 google 中找到的所有解决方案,但仍然没有成功。你能帮我个忙吗? 这是我的服务层:
@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。如果第一次成功而第二次失败,则数据库中的第一个 table 不会回滚。 下面是 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" />
请你告诉我为什么服务层方法上的@Transactional 不起作用。谢谢。
您可能应该使用 HibernateTransactionManager 而不是 DataSourceTransactionManager。
使用
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
而不是
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
还要检查调用服务的位置。如果您从服务 class 本身调用它,将不会使用处理事务管理的代理。