序言 - 使用 Spring
我對 spring @Transactional 注釋的目的感到困惑。我從我讀過的幾篇博客文章中想到,它可以讓我簡化事務管理,只需撰寫它,它就會自動處理連接/提交/回滾:
public class DaoImpl implements Dao {
@Autowired
private SessionFactory sessionFactory;
@Transactional
public void saveOrUpdateOne(final AdditionalDataItem item) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(p_item);
}
}
但是,這給了我一個例外:“沒有活動事務,呼叫方法‘saveOrUpdate’無效”
如果我改為將 save 方法更改為此,則一切正常 - 所以我的問題是,@Transactional 在做什么?
@Override
@Transactional
public void saveOrUpdateOne(final AdditionalDataItem p_item) {
Session session = null;
Transaction trans = null;
try {
session = sessionFactory.getCurrentSession();
trans = session.beginTransaction();
TransactionStatus status = trans.getStatus();
session.saveOrUpdate(p_item);
trans.commit();
} catch (Exception e) {
LOGGER.error("Exception saving data: {}", e.getMessage());
if (trans != null) {
try {
trans.rollback();
} catch (RuntimeException rbe) {
LOGGER.error("Couldn’t roll back transaction", rbe);
}
}
} finally {
if (session != null && session.isOpen()) {
try {
session.close();
} catch (HibernateException ne) {
LOGGER.error("Couldn’t close session", ne);
}
}
}
}
作為參考,我將 Java 11 與 Spring Framework 5.3.7 和 hibernate 5.5.7 一起使用,并具有適當的 dao、會話工廠和 tx 管理器 bean:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="${sessionFactory.datasource}" />
<property name="configLocation" value="${sessionFactory.configLocation}" />
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="Dao" class="com.xxxxx.dao.DaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
uj5u.com熱心網友回復:
這是因為您尚未啟用@Transactional并且在呼叫 時也未開始交易session.saveOrUpdate(),因此它會給您錯誤“沒有活動交易無效”。
要啟用@Transactional,您必須使用@EnableTransactionManagement或添加<tx:annotation-driven/>以防您使用 XML 配置。它基本上為您執行以下操作(來源):
@EnableTransactionManagement 和 <tx:annotation-driven/> 負責注冊必要的 Spring 組件,這些組件為注解驅動的事務管理提供支持,例如
TransactionInterceptor當 JdbcFooRepository 的 @事務方法被呼叫。
您的作業示例有效,因為您自己手動管理事務。@Transactional因為您從未啟用它,所以與此無關。
以作業代碼為例,@Transactional對你來說,你不再需要手動撰寫以下事務代碼,因為它們都將封裝在基于AOPTransactionInterceptor的@Transactional方法周圍并執行:
public Object invoke() {
Session session = null;
Transaction trans = null;
try {
session = sessionFactory.getCurrentSession();
trans = session.beginTransaction();
TransactionStatus status = trans.getStatus();
/***********************************************/
Here it will invoke your @Transactional Method
/************************************************/
trans.commit();
} catch (Exception e) {
LOGGER.error("Exception saving data: {}", e.getMessage());
if (trans != null) {
try {
trans.rollback();
} catch (RuntimeException rbe) {
LOGGER.error("Couldn’t roll back transaction", rbe);
}
}
} finally {
if (session != null && session.isOpen()) {
try {
session.close();
} catch (HibernateException ne) {
LOGGER.error("Couldn’t close session", ne);
}
}
}
}
所以你可以看到,@Transactional去掉這些“儀式”代碼后,你的方法會變得非常干凈。
uj5u.com熱心網友回復:
如果要更新 2 個表,則使用 @Transactional 如果其中一個失敗,另一個將自動回滾,您可以使用上面的方法,并且可以使用 Repository 類的 bean 呼叫 save 或 update
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/337477.html
上一篇:休眠程式掛起,沒有任何日志
