@Transactional注解異常報(bào)錯(cuò)之多數(shù)據(jù)源詳解
@Transactional注解報(bào)錯(cuò)之多數(shù)據(jù)源
如果在加上@Transactional注解之后報(bào)錯(cuò),先查看程序是否為多數(shù)據(jù)源,之前專門有一章講解springboot的多數(shù)據(jù)源實(shí)現(xiàn)。多數(shù)據(jù)源的情況下加事物注解,有可能會(huì)出現(xiàn)問題,以下是解決方案。
1.在配置數(shù)據(jù)源的同時(shí)
一定到在其中一個(gè)配置上加上@Primary注解,其他的不要加。
package com.wys.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
/**
* @program:
* @description: 數(shù)據(jù)庫配置1
* @author: wys
* @create: 2019-12-03 16:20
**/
@Configuration
@MapperScan(basePackages = "com.wys.mapper.**", sqlSessionFactoryRef = "oneSqlSessionFactory")
public class OneDataSourceConfig {
@Value("${spring.datasource.one.driver-class-name}")
String driverClass;
@Value("${spring.datasource.one.url}")
String url;
@Value("${spring.datasource.one.username}")
String userName;
@Value("${spring.datasource.one.password}")
String passWord;
@Primary
@Bean(name = "oneDataSource")
@ConfigurationProperties("spring.datasource.one")
public DataSource masterDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(passWord);
return dataSource;
}
@Bean(name = "oneSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mybatis/mapper-postgre/*.xml"));
return sessionFactoryBean.getObject();
}
@Bean(name = "oneSqlSessionFactory")
public SqlSessionTemplate sqlSessionFactoryTemplate(@Qualifier("oneSqlSessionFactory")SqlSessionFactory sqlSessionFactory ) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
2.一定要在需要使用事物注解的數(shù)據(jù)源配置里
加上創(chuàng)建事務(wù)管理器
package com.wys.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
/**
* @program:
* @description: 數(shù)據(jù)庫配置1
* @author: wys
* @create: 2019-12-03 16:20
**/
@Configuration
@MapperScan(basePackages = "com.wys.mapper.**", sqlSessionFactoryRef = "oneSqlSessionFactory")
public class OneDataSourceConfig {
@Value("${spring.datasource.one.driver-class-name}")
String driverClass;
@Value("${spring.datasource.one.url}")
String url;
@Value("${spring.datasource.one.username}")
String userName;
@Value("${spring.datasource.one.password}")
String passWord;
@Primary
@Bean(name = "oneDataSource")
@ConfigurationProperties("spring.datasource.one")
public DataSource masterDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(passWord);
return dataSource;
}
@Bean(name = "oneSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mybatis/mapper-postgre/*.xml"));
return sessionFactoryBean.getObject();
}
/
// 創(chuàng)建事務(wù)管理器1
@Bean(name = "oneManager1")
public PlatformTransactionManager txManager(@Qualifier("oneDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/////////////////////////
@Bean(name = "oneSqlSessionFactory")
public SqlSessionTemplate sqlSessionFactoryTemplate(@Qualifier("oneSqlSessionFactory")SqlSessionFactory sqlSessionFactory ) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
在需要加注解的地方加上transactionManager 配置即可。
@Transactional(transactionManager ="oneManager1",rollbackFor=Exception.class)
@Transactional 錯(cuò)誤使用的幾種場(chǎng)景
@RestController
public class AController {
@Autowired
AService aService;
// 回滾
@GetMapping("direct")
public void direct() {
aService.testTransactional();
}
// 不回滾
@GetMapping("indirect")
public void indirect() {
aService.testTransactionalIndirect();
}
// 不回滾
@GetMapping("nonPublic")
public void nonPublic() {
aService.testTransactionalNonPublic();
}
// 不回滾
@GetMapping("catchException")
public void catchException() {
aService.testTransactionalCatchException();
}
// 不回滾
@GetMapping("sqlException")
public void sqlException() throws SQLException {
aService.testTransactionalSQLException();
}
// 回滾
@GetMapping("sqlExceptionWithRollbackfor")
public void sqlExceptionWithRollbackfor() throws SQLException {
aService.testTransactionalSQLExceptionWithRollbackfor();
}
}@Service
public class AService {
@Autowired
TestTableDAO testTableDAO;
// 回滾
@Transactional
public void testTransactional() {
ATestTable er = new ATestTable();
er.setSummary("test");
testTableDAO.save(er);
throw new RuntimeException("exception");
}
// 不回滾: 類內(nèi)部方法調(diào)用本類內(nèi)部的其他方法并不會(huì)引起事務(wù)行為,即使被調(diào)用方法使用@Transactional注解進(jìn)行修飾
public void testTransactionalIndirect() {
testTransactional();
}
// 不回滾: @Transaction注解只對(duì)方法名為pubic的才生效
@Transactional
void testTransactionalNonPublic() {
ATestTable er = new ATestTable();
er.setSummary("test");
testTableDAO.save(er);
throw new RuntimeException("exception");
}
// 不回滾
@Transactional
public void testTransactionalCatchException() {
ATestTable er = new ATestTable();
er.setSummary("test");
testTableDAO.save(er);
try {
throw new RuntimeException("exception");
} catch (Exception e) {
System.out.println("catch");
}
}
// 不回滾: @Transactional默認(rèn)情況下只回滾RuntimeException和Error
@Transactional
public void testTransactionalSQLException() throws SQLException {
ATestTable er = new ATestTable();
er.setSummary("test");
testTableDAO.save(er);
throw new SQLException("exception");
}
// 回滾: 指定在 SQLException 異常發(fā)生時(shí)回滾
@Transactional(rollbackFor = {
SQLException.class
})
public void testTransactionalSQLExceptionWithRollbackfor() throws SQLException {
ATestTable er = new ATestTable();
er.setSummary("test");
testTableDAO.save(er);
throw new SQLException("exception");
}
}@Repository
public interface TestTableDAO
extends JpaRepository<ATestTable, Integer>, JpaSpecificationExecutor<ATestTable> {
}@Entity
@Data
@Table(name = "test")
public class ATestTable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
@Column(name = "summary", length = 512)
String summary;
}以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Shiro與Springboot整合開發(fā)的基本步驟過程詳解
這篇文章主要介紹了Shiro與Springboot整合開發(fā)的基本步驟,本文結(jié)合實(shí)例代碼給大家介紹整合過程,感興趣的朋友跟隨小編一起看看吧2023-06-06
Spring Cloud gateway 網(wǎng)關(guān)如何攔截Post請(qǐng)求日志
這篇文章主要介紹了Spring Cloud gateway 網(wǎng)關(guān)如何攔截Post請(qǐng)求日志的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot使用thymeleaf實(shí)現(xiàn)前端表格
雖然現(xiàn)在流行前后端分離,但是后端模版在一些關(guān)鍵地方還是非常有用的,例如郵件模版、代碼模版等。當(dāng)然也不排除一些古老的項(xiàng)目后端依然使用動(dòng)態(tài)模版。Thymeleaf 簡(jiǎn)潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態(tài)頁面,同時(shí)不新增標(biāo)簽,只需增強(qiáng)屬性2022-10-10
Springboot啟動(dòng)不檢查JPA的數(shù)據(jù)源配置方式
這篇文章主要介紹了Springboot啟動(dòng)不檢查JPA的數(shù)據(jù)源配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
mybatis整合ehcache做三級(jí)緩存的實(shí)現(xiàn)方法
ehcache是一個(gè)快速內(nèi)存緩存框架,java項(xiàng)目里用起來很方便,下面這篇文章主要給大家介紹了關(guān)于mybatis整合ehcache做三級(jí)緩存的實(shí)現(xiàn)方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
Java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生教師管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生教師管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Intellij IDEA中如何查看maven項(xiàng)目中所有jar包的依賴關(guān)系圖
這篇文章主要介紹了Intellij IDEA中如何查看maven項(xiàng)目中所有jar包的依賴關(guān)系圖,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05

