Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize dynamic switching of distributed transaction data sources by Jdbc

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report