In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how to achieve dynamic switching of distributed transaction data sources by Jdbc". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
One: dependent jar package Maven configuration
Com.atomikos
Transactions
4.0.4
Com.atomikos
Transactions-api
4.0.4
Com.atomikos
Atomikos-util
4.0.4
Com.atomikos
Transactions-jdbc-deprecated
3.8.0
Com.atomikos
Transactions-jta
4.0.4
Com.atomikos
Transactions-jdbc
4.0.4
Cglib
Cglib-nodep
3.2.5
Javax.transaction
Jta
1.1
Two: configuration
DataSource.properties
Click (here) to collapse or open
WorkDesk.jdbc.driverclass=com.mysql.jdbc.Driver
WorkDesk.jdbc.url=jdbc:mysql://10.243.3.18:3306/system?userUnicode=true&characterEncoding=UTF-8
WorkDesk.jdbc.username=root
WorkDesk.jdbc.password=$Fortune2015
WorkDesk.jdbc.poolsize.max=3
WorkDesk.jdbc.poolsize.min=3
WorkDesk.jdbc.poolsize.initial=2
WorkDesk.jdbc.idletime.max=25000
WorkDesk.jdbc.idleConnectionTestPeriod=18000
#-workDesk jdbc-
WorkDesk.read.jdbc.driverclass=com.mysql.jdbc.Driver
WorkDesk.read.jdbc.url=jdbc:mysql://112.74.53.213:3306/gmc?userUnicode=true&characterEncoding=UTF-8
WorkDesk.read.jdbc.username=root
WorkDesk.read.jdbc.password=Wanmide@123
WorkDesk.read.jdbc.poolsize.max=3
WorkDesk.read.jdbc.poolsize.min=3
WorkDesk.read.jdbc.poolsize.initial=2
WorkDesk.read.jdbc.idletime.max=25000
WorkDesk.read.jdbc.idleConnectionTestPeriod=18000
Jdbc.xaDataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
Transactions.properties
Click (here) to collapse or open
# SAMPLE PROPERTIES FILE FOR THE TRANSACTION SERVICE
# THIS FILE ILLUSTRATES THE DIFFERENT SETTINGS FOR THE TRANSACTION MANAGER
# UNCOMMENT THE ASSIGNMENTS TO OVERRIDE DEFAULT VALUES
# Required: factory implementation class of the transaction core.
# NOTE: there is no default for this, so it MUST be
#
Com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
# Set base name of file where messages are output
# (also known as the 'console file').
#
# com.atomikos.icatch.console_file_name = tm.out
# Size limit (in bytes) for the console file
# negative means unlimited.
#
# com.atomikos.icatch.console_file_limit=-1
# For size-limited console files, this option
# specifies a number of rotating files to
# maintain.
#
# com.atomikos.icatch.console_file_count=1
# Set the number of log writes between checkpoints
#
# com.atomikos.icatch.checkpoint_interval=500
# Set output directory where console file and other files are to be put
# make sure this directory
#
# com.atomikos.icatch.output_dir =. /
# Set directory of log files; make sure this directory
#
Com.atomikos.icatch.log_base_dir =. /
# Set base name of log file
# this name will be used as the first part of
# the system-generated log file name
#
# com.atomikos.icatch.log_base_name = tmlog
# Set the max number of active local transactions
# or-1 for unlimited.
#
# com.atomikos.icatch.max_actives = 50
# Set the default timeout (in milliseconds) for local transactions
#
# com.atomikos.icatch.default_jta_timeout = 10000
# Set the max timeout (in milliseconds) for local transactions
#
# com.atomikos.icatch.max_timeout = 300000
# The globally unique name of this transaction manager process
# override this value with a globally unique name
#
# com.atomikos.icatch.tm_unique_name = tm
# Do we want to use parallel subtransactions? JTA
Click (here) to collapse or open
/ * *
* Atomikos data source A
* @ return
, /
@ Bean (name= "dataSourceA", initMethod= "init", destroyMethod= "close")
Public AtomikosDataSourceBean dataSourceA ()
{
AtomikosDataSourceBean dataSourceA=new AtomikosDataSourceBean ()
DataSourceA.setUniqueResourceName ("dataSourceA")
DataSourceA.setXaDataSourceClassName (xaDataSourceClassName)
Properties xaProperties = new Properties ()
XaProperties.put ("user", user)
XaProperties.put ("password", password)
XaProperties.put ("url", jdbcUrl)
XaProperties.put ("pinGlobalTxToPhysicalConnection", true)
DataSourceA.setXaProperties (xaProperties)
DataSourceA.setMaxPoolSize (maxPoolSize)
DataSourceA.setMinPoolSize (minPoolSize)
DataSourceA.setMaxIdleTime (maxIdleTime)
DataSourceA.setTestQuery ("SELECT 1")
Return dataSourceA
}
/ * *
* Atomikos data source A
* @ return
, /
@ Bean (name= "dataSourceB", initMethod= "init", destroyMethod= "close")
Public AtomikosDataSourceBean dataSourceB ()
{
AtomikosDataSourceBean dataSourceA=new AtomikosDataSourceBean ()
DataSourceA.setUniqueResourceName ("dataSourceB")
DataSourceA.setXaDataSourceClassName (xaDataSourceClassName)
Properties xaProperties = new Properties ()
XaProperties.put ("user", readUser)
XaProperties.put ("password", readPassword)
XaProperties.put ("url", readJdbcUrl)
XaProperties.put ("pinGlobalTxToPhysicalConnection", true)
DataSourceA.setXaProperties (xaProperties)
DataSourceA.setMaxPoolSize (readMaxPoolSize)
DataSourceA.setMinPoolSize (readMinPoolSize)
DataSourceA.setMaxIdleTime (readMaxIdleTime)
DataSourceA.setTestQuery ("SELECT 1")
Return dataSourceA
}
Click (here) to collapse or open
@ Configuration
Public class DynamicTransactionManagerElConfig {
/ / @ Autowired
/ / @ Qualifier ("platformTomcat")
/ / private DataSource platformTomcat
/ /
/ / @ Autowired
/ / @ Qualifier ("platformReadTomcat")
/ / private DataSource platformReadTomcat
@ Autowired
@ Qualifier ("dataSourceA")
Private DataSource dataSourceA
@ Autowired
@ Qualifier ("dataSourceB")
Private DataSource dataSourceB
@ Bean (name = "dataSource")
Public DynamicDataSource dataSource () {
DynamicDataSource dataSource = new DynamicDataSource ()
Map targetDataSources = new HashMap ()
TargetDataSources.put ("master", dataSourceA)
TargetDataSources.put ("slave", dataSourceB)
DataSource.setTargetDataSources (targetDataSources)
DataSource.setDefaultTargetDataSource (dataSourceA)
Return dataSource
}
@ Bean (name = "jdbcTemplate")
Public JdbcTemplate jdbcTemplate (DynamicDataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate ()
JdbcTemplate.setDataSource (dataSource)
Return jdbcTemplate
}
@ Bean (name = "jdbcReadTemplate")
Public JdbcTemplate jdbcReadTemplate (DynamicDataSource dataSource) {
JdbcTemplate jdbcReadTemplate = new JdbcTemplate ()
JdbcReadTemplate.setDataSource (dataSource)
Return jdbcReadTemplate
}
@ Bean (name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
Public UserTransactionManager atomikosTransactionManager () {
UserTransactionManager atomikosTransactionManager = new UserTransactionManager ()
AtomikosTransactionManager.setForceShutdown (true)
Return atomikosTransactionManager
}
@ Bean (name = "atomikosUserTransaction")
Public UserTransactionImp atomikosUserTransaction () {
UserTransactionImp atomikosUserTransaction = new UserTransactionImp ()
Try {
AtomikosUserTransaction.setTransactionTimeout (300)
}
Catch (SystemException e) {
E.printStackTrace ()
}
Return atomikosUserTransaction
}
/ / @ Bean (name = "transactionManager")
/ / public DataSourceTransactionManager transactionManager (DynamicDataSource
/ / dataSource) {
/ / DataSourceTransactionManager transactionManager = new
/ / DataSourceTransactionManager ()
/ / transactionManager.setDataSource (dataSource)
/ / return transactionManager
/ /}
@ Bean (name = "transactionManager")
Public JtaTransactionManager transactionManager (UserTransactionManager atomikosTransactionManager
UserTransactionImp atomikosUserTransaction) {
JtaTransactionManager transactionManager = new JtaTransactionManager ()
TransactionManager.setTransactionManager (atomikosTransactionManager)
TransactionManager.setUserTransaction (atomikosUserTransaction)
TransactionManager.setAllowCustomIsolationLevels (true)
Return transactionManager
}
}
Third, AOP annotation mode data source dynamic switching
Click (here) to collapse or open
@ Retention (RetentionPolicy.RUNTIME)
@ Target (ElementType.METHOD)
@ Documented
Public @ interface DataSource {
String value ()
}
Click (here) to collapse or open
Public class DynamicDataSource extends AbstractRoutingDataSource {
@ Override
Protected Object determineCurrentLookupKey () {
Return DataSourceContextHolder.getDataSource ()
}
}
Click (here) to collapse or open
Public class DataSourceContextHolder {
Private static final ThreadLocal contextHolder = new ThreadLocal ()
Public static void setDataSource (String dataSource) {
ContextHolder.set (dataSource)
}
Public static String getDataSource () {
Return contextHolder.get ()
}
Public static void removeDataSource () {
ContextHolder.remove ()
}
}
Click (here) to collapse or open
@ Aspect
@ Order (1)
@ Component
Public class DataSourceAspect {
@ Pointcut ("@ annotation (com.gemdale.ghome.business.async.deal.center.demo.datasource.DataSource)")
Public void dataSourcePointCut () {
}
@ Before ("dataSourcePointCut ()")
Public void before (JoinPoint joinPoint) {
System.out.println ("= dataSourcePointCut:before=")
Object target = joinPoint.getTarget ()
String method = joinPoint.getSignature () .getName ()
/ / Class [] classz = target.getClass () .getInterfaces ()
Class classz = target.getClass ()
Class [] parameterTypes = ((MethodSignature) joinPoint.getSignature ()) .getMethod () .getParameterTypes ()
Try {
/ / Method m = classz [0] .getMethod (method, parameterTypes)
Method m = classz.getMethod (method, parameterTypes)
If (null! = m & & m.isAnnotationPresent (DataSource.class)) {
DataSource dataSource = m.getAnnotation (DataSource.class)
DataSourceContextHolder.setDataSource (dataSource.value ())
System.out.println ("= dataSource:" + dataSource.value ())
}
}
Catch (Exception e) {
E.printStackTrace ()
}
}
}
Four: dynamically switch instances of data sources
Click (here) to collapse or open
@ Repository ("gmcSmsInfoDaoImpl")
Public class GmcSmsInfoDaoImpl extends BaseDaoSupport implements GmcSmsInfoDAO {
/ * (non-Javadoc)
* @ see com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfoDAO#addMaster (com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfo)
, /
@ Override
@ DataSource ("master")
Public Integer addMaster (GmcSmsInfo smsInfo) throws FrameworkDAOException {
Return save (smsInfo)
}
/ * (non-Javadoc)
* @ see com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfoDAO#addSlave (com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfo)
, /
@ Override
@ DataSource ("slave")
Public Integer addSlave (GmcSmsInfo smsInfo) throws FrameworkDAOException {
Return save (smsInfo)
}
}
Fifth: dynamic switching of data sources under distributed transactions
Case 1: switching of unique data sources under transactions
Click (here) to collapse or open
@ Transactional (rollbackFor= {Exception.class,RuntimeException.class})
@ DataSource ("master")
Public GmcSmsInfo addMaster (GmcSmsInfo smsInfo) throws BusinessServiceException {
Try {
SmsInfo.setSmsId (gmcSmsInfoDaoImpl.save (smsInfo))
}
Catch (FrameworkDAOException e) {
Throw new BusinessServiceException (e)
}
Return smsInfo
}
@ Transactional establishes a transaction through the connection of the database. In order to ensure that the data source can be switched smoothly, make sure that @ DataSource takes precedence over @ Transactional. The implementation method adds the annotation @ Order (1) to the DataSourceAspect section. Here you need to know the level of the aspect and the order of execution and so on. @ Transactionl,@DataSource is on the same method in the service layer.
Case 2: multi-data source switching under transaction
Service class
Click (here) to collapse or open
@ Autowired
Private GmcSmsInfoDAO gmcSmsInfoDaoImpl
@ Autowired
@ Qualifier ("transactionManager")
Private JtaTransactionManager transactionManager
Public void addMasterAndSlave (GmcSmsInfo smsInfo) throws BusinessServiceException {
UserTransaction userTransaction = transactionManager.getUserTransaction ()
Try {
UserTransaction.begin ()
GmcSmsInfoDaoImpl.addMaster (smsInfo)
SmsInfo = new GmcSmsInfo ()
SmsInfo.setChannel ("test2")
SmsInfo.setContent ("test2")
SmsInfo.setStatus ("001")
SmsInfo.setCreateDate (Calendar.getInstance () .getTime ())
SmsInfo.setMobile ("88888888")
GmcSmsInfoDaoImpl.addSlave (smsInfo)
UserTransaction.commit ()
}
Catch (Exception e) {
Try {
UserTransaction.rollback ()
}
Catch (IllegalStateException E1) {
E1.printStackTrace ()
}
Catch (SecurityException E1) {
E1.printStackTrace ()
}
Catch (SystemException E1) {
E1.printStackTrace ()
}
Throw new BusinessServiceException (e)
}
}
Dao implementation class
Click (here) to collapse or open
/ * (non-Javadoc)
* @ see com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfoDAO#addMaster (com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfo)
, /
@ Override
@ DataSource ("master")
Public Integer addMaster (GmcSmsInfo smsInfo) throws FrameworkDAOException {
Return save (smsInfo)
}
/ * (non-Javadoc)
* @ see com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfoDAO#addSlave (com.gemdale.ghome.business.async.deal.center.demo.GmcSmsInfo)
, /
@ Override
@ DataSource ("slave")
Public Integer addSlave (GmcSmsInfo smsInfo) throws FrameworkDAOException {
Return save (smsInfo)
}
Note that programming is used to implement transactions here, and there is no good solution for annotated type for the time being. You are welcome to discuss and share. The @ DataSource here is placed in the implementation layer of dao.
This is the end of the content of "how to achieve dynamic switching of distributed transaction data sources in Jdbc". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.