springboot 动态数据源切换

本文介绍了一个SpringBoot应用中实现多数据源切换的实例,包括配置两个数据库的基本信息,使用Druid数据源,动态数据源路由,以及在业务层切换数据源的示例代码。通过设置`DatabaseContextHolder`上下文来切换数据源,适用于读写分离或不同业务数据统计的场景。注意,事务管理前需确保切换到正确数据源。

多数据源切换Springboot实现

        之前踩了很多坑才弄明白的,可以用来做多库数据统计,读写分离之类的场景

       当然上代码

  

server:
  port: 8080
servlet:
  context-path: /
spring:
  profiles:
    active: dev
# 数据源相关配置
ds:
  # 数据库1
  basic:
    datasource:
      url: jdbc:mysql://192.168.1.88:3306/cc-game-mili?useUnicode=true&characterEncoding=utf8&useSSL=false&useAffectedRows=true&serverTimezone=GMT
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver
  # 数据库2
  base:
    datasource:
      url: jdbc:mysql://192.168.1.100:3306/company_frame?useUnicode=true&characterEncoding=utf8&useSSL=false&useAffectedRows=true&serverTimezone=GMT
      username: root
      password: baishou888
      driver-class-name: com.mysql.jdbc.Driver

  # 连接池配置
  datasource:
    initial_size: 20
    min_idle: 20
    max_active: 200
    max_wait: 60000
    time_between_eviction_runs_millis: 60000
    min_evictable_idle_time_millis: 300000
    test_while_idle: true
    test_on_borrow: false
    test_on_return: false
    pool_prepared_statements: true
    max_pool_prepared_statement_per_connection_size: 20


## JPA 相关配置
#spring:
#  jpa:
#    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
#    show-sql: true
# mybatis 打印sql
logging:
  level:
    com.hzw.mapper : debug
package com.zkb.config;

/**
 * 自定义数据源切换类
 */
public class DatabaseContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public static void setDBKey(String dataSourceKey) {
        contextHolder.set(dataSourceKey);
    }

    public static String getDBKey() {
        return contextHolder.get();
    }

    public static void clearDBKey() {
        contextHolder.remove();
    }
}
package com.zkb.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.zkb.util.DbUtil;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
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.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * 数据源配置
 */
@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = DatasourceConfig.PACKAGE, sqlSessionFactoryRef = "sqlSessionFactory")
public class DatasourceConfig {
    // mapper扫描
    static final String PACKAGE = "com.zkb.mapper";
    static final String MAPPER_LOCATION = "classpath:mapper/*.xml";

    @Value("${ds.basic.datasource.url}")
    private String urlBasic;
    @Value("${ds.basic.datasource.username}")
    private String userBasic;
    @Value("${ds.basic.datasource.password}")
    private String passwordBasic;
    @Value("${ds.basic.datasource.driver-class-name}")
    private String driverClassBasic;

    @Value("${ds.base.datasource.url}")
    private String urlBase;
    @Value("${ds.base.datasource.username}")
    private String userBase;
    @Value("${ds.base.datasource.password}")
    private String passwordBase;
    @Value("${ds.base.datasource.driver-class-name}")
    private String driverClassBase;



    @Value("${ds.datasource.max_active}")
    private Integer maxActive;
    @Value("${ds.datasource.min_idle}")
    private Integer minIdle;
    @Value("${ds.datasource.initial_size}")
    private Integer initialSize;
    @Value("${ds.datasource.max_wait}")
    private Long maxWait;
    @Value("${ds.datasource.time_between_eviction_runs_millis}")
    private Long timeBetweenEvictionRunsMillis;
    @Value("${ds.datasource.min_evictable_idle_time_millis}")
    private Long minEvictableIdleTimeMillis;
    @Value("${ds.datasource.test_while_idle}")
    private Boolean testWhileIdle;
    @Value("${ds.datasource.test_while_idle}")
    private Boolean testOnBorrow;
    @Value("${ds.datasource.test_on_borrow}")
    private Boolean testOnReturn;

    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = DynamicDataSource.getInstance();

        // basic数据源
        DruidDataSource dataSourceBasic = initDataSource(driverClassBasic,urlBasic,userBasic,passwordBasic);
        // base数据源
        DruidDataSource dataSourceBase = initDataSource(driverClassBase,urlBase,userBase,passwordBase);

        Map<Object,Object> map = new HashMap<>();
        map.put(DbUtil.DB_BASIC, dataSourceBasic);
        map.put(DbUtil.DB_BASE, dataSourceBase);


        dynamicDataSource.setTargetDataSources(map);
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSourceBasic);
        return dynamicDataSource;
    }

    /**
     * 初始数据源
     * @param driver    驱动
     * @param url       数据库连接
     * @param username  用户名
     * @param password  密码
     * @return
     */
    public DruidDataSource initDataSource(String driver,String url,String username,String password){
        //jdbc配置
        DruidDataSource rdataSource = new DruidDataSource();
        rdataSource.setDriverClassName(driver);
        rdataSource.setUrl(url);
        rdataSource.setUsername(username);
        rdataSource.setPassword(password);
        setPool(rdataSource);
        return rdataSource;
    }

    /**
     * 连接池配置
     * @param rdataSource
     */
    private void setPool(DruidDataSource rdataSource){
        //连接池配置
        rdataSource.setMaxActive(maxActive);
        rdataSource.setMinIdle(minIdle);
        rdataSource.setInitialSize(initialSize);
        rdataSource.setMaxWait(maxWait);
        rdataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        rdataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        rdataSource.setTestWhileIdle(testWhileIdle);
        rdataSource.setTestOnBorrow(testOnBorrow);
        rdataSource.setTestOnReturn(testOnReturn);
        rdataSource.setValidationQuery("SELECT 'x'");
        rdataSource.setPoolPreparedStatements(true);
        rdataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
        try {
            rdataSource.setFilters("stat");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Bean(name = "transactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }

    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource);
        sessionFactory.setTypeAliasesPackage("com.hzw.model");
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(DatasourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }


    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
        servletRegistrationBean.setServlet(new StatViewServlet());
        servletRegistrationBean.addUrlMappings("/druid/*");
        Map<String, String> initParameters = new HashMap<String, String>();
        // 用户名
        initParameters.put("loginUsername", "admin");
        // 密码
        initParameters.put("loginPassword", "admin");
        // 禁用HTML页面上的“Reset All”功能
        initParameters.put("resetEnable", "false");
        // IP白名单 (没有配置或者为空,则允许所有访问)
        initParameters.put("allow", "");
        servletRegistrationBean.setInitParameters(initParameters);
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

}
package com.zkb.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import java.util.HashMap;
import java.util.Map;

/**
 * 动态数据源
 *
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static DynamicDataSource instance;
    private static byte[] lock=new byte[0];
    private static Map<Object,Object> dataSourceMap=new HashMap<Object, Object>();

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        dataSourceMap.putAll(targetDataSources);
        // 必须添加该句,否则新添加数据源无法识别到
        super.afterPropertiesSet();
    }

    public Map<Object, Object> getDataSourceMap() {
        return dataSourceMap;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String dbKey = DatabaseContextHolder.getDBKey();
        return dbKey;
    }

    private DynamicDataSource() {}

    public static synchronized DynamicDataSource getInstance(){
        if(instance==null){
            synchronized (lock){
                if(instance==null){
                    instance=new DynamicDataSource();
                }
            }
        }
        return instance;
    }

}
package com.zkb.controller;

import com.zkb.model.GameAccounts;
import com.zkb.model.GameOrders;
import com.zkb.service.GameAccountService;
import com.zkb.service.GameOrdersService;
import com.zkb.util.DbUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * 测试控制器
 */
@Controller
public class TestController {


    @Autowired
     GameAccountService gameAccountService;
    @Autowired
    GameOrdersService gameOrdersService;



    @RequestMapping("findGameAccounts")
    @ResponseBody
    public String findGameAccounts() {

        GameAccounts gameAccounts = gameAccountService.selectBylast();

        int hs =0;
        if (!ObjectUtils.isEmpty(gameAccounts)){
            hs=gameAccounts.getId();
        }
        // 指定数据源
        List<GameAccounts> list =gameAccountService.findGameAccounts(hs);

        if (!CollectionUtils.isEmpty(list)) {
            System.out.println("执行了");
            gameAccountService.insertBatchAccount(list);
        }
        return "SUCCESS";

    }

    @RequestMapping("findGameOrders")
    @ResponseBody
    public String findGameOrders() {
        // 指定数据源
        Integer gameCount = gameOrdersService.selectCount(DbUtil.DB_BASIC); //游戏库总数
        Integer adminCount = gameOrdersService.selectCount(DbUtil.DB_BASE);  //管理后台库总数
        List<GameOrders> list= gameOrdersService.findGameOrders(adminCount,gameCount);
        if (!CollectionUtils.isEmpty(list)) {
            System.out.println("执行了");
            gameOrdersService.insertBatchOrder(list);
        }
        return "SUCCESS";
    }

}
package com.zkb.mapper;

import com.zkb.model.GameAccounts;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface GameAccountsMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(GameAccounts record);

    int insertSelective(GameAccounts record);

    GameAccounts selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(GameAccounts record);

    int updateByPrimaryKey(GameAccounts record);

    List<GameAccounts> findGameAccounts(@Param("hs") int hs);

    GameAccounts selectBylast();

    void insertBatchAccount(List<GameAccounts> list);
}
package com.zkb.mapper;

import com.zkb.model.GameOrders;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface GameOrdersMapper {
    int deleteByPrimaryKey(String orderId);

    int insert(GameOrders record);

    int insertSelective(GameOrders record);

    GameOrders selectByPrimaryKey(String orderId);

    int updateByPrimaryKeySelective(GameOrders record);

    int updateByPrimaryKey(GameOrders record);

    List<GameOrders> findGameOrders(@Param("hs")int hs,@Param("count")int count);

    GameOrders selectBylast();

    int selectCount();

    void insertBatchOrder(List<GameOrders> list);
}
package com.zkb.model;

import java.io.Serializable;
import java.util.Date;


public class GameAccounts implements Serializable {
    private Integer id;

    private String account;

    private String bindPhone;

    private String password;

    private String distributors;

    private String distCode;

    private Integer channelId;

    private String channel;

    private Date regdate;

    private String deviceid;

    private Date logintime;

    private String loginip;

    private String loginkey;

    private Integer flag;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account == null ? null : account.trim();
    }

    public String getBindPhone() {
        return bindPhone;
    }

    public void setBindPhone(String bindPhone) {
        this.bindPhone = bindPhone == null ? null : bindPhone.trim();
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }

    public String getDistributors() {
        return distributors;
    }

    public void setDistributors(String distributors) {
        this.distributors = distributors == null ? null : distributors.trim();
    }

    public String getDistCode() {
        return distCode;
    }

    public void setDistCode(String distCode) {
        this.distCode = distCode == null ? null : distCode.trim();
    }

    public Integer getChannelId() {
        return channelId;
    }

    public void setChannelId(Integer channelId) {
        this.channelId = channelId;
    }

    public String getChannel() {
        return channel;
    }

    public void setChannel(String channel) {
        this.channel = channel == null ? null : channel.trim();
    }

    public Date getRegdate() {
        return regdate;
    }

    public void setRegdate(Date regdate) {
        this.regdate = regdate;
    }

    public String getDeviceid() {
        return deviceid;
    }

    public void setDeviceid(String deviceid) {
        this.deviceid = deviceid == null ? null : deviceid.trim();
    }

    public Date getLogintime() {
        return logintime;
    }

    public void setLogintime(Date logintime) {
        this.logintime = logintime;
    }

    public String getLoginip() {
        return loginip;
    }

    public void setLoginip(String loginip) {
        this.loginip = loginip == null ? null : loginip.trim();
    }

    public String getLoginkey() {
        return loginkey;
    }

    public void setLoginkey(String loginkey) {
        this.loginkey = loginkey == null ? null : loginkey.trim();
    }

    public Integer getFlag() {
        return flag;
    }

    public void setFlag(Integer flag) {
        this.flag = flag;
    }
}
package com.zkb.model;

import java.util.Date;

public class GameOrders {
    private String orderId;

    private String ticketId;

    private String distributors;

    private String distCode;

    private String channelId;

    private Float amount;

    private Integer payStatus;

    private String payTime;

    private String transactionId;

    private String account;

    private Integer serverId;

    private String chrName;

    private String orderType;

    private Integer productId;

    private String productName;

    private Integer giveVcoin;

    private Integer giveVcb;

    private String channelProductId;

    private String privateData;

    private Date orderTime;

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId == null ? null : orderId.trim();
    }

    public String getTicketId() {
        return ticketId;
    }

    public void setTicketId(String ticketId) {
        this.ticketId = ticketId == null ? null : ticketId.trim();
    }

    public String getDistributors() {
        return distributors;
    }

    public void setDistributors(String distributors) {
        this.distributors = distributors == null ? null : distributors.trim();
    }

    public String getDistCode() {
        return distCode;
    }

    public void setDistCode(String distCode) {
        this.distCode = distCode == null ? null : distCode.trim();
    }

    public String getChannelId() {
        return channelId;
    }

    public void setChannelId(String channelId) {
        this.channelId = channelId == null ? null : channelId.trim();
    }

    public Float getAmount() {
        return amount;
    }

    public void setAmount(Float amount) {
        this.amount = amount;
    }

    public Integer getPayStatus() {
        return payStatus;
    }

    public void setPayStatus(Integer payStatus) {
        this.payStatus = payStatus;
    }

    public String getPayTime() {
        return payTime;
    }

    public void setPayTime(String payTime) {
        this.payTime = payTime == null ? null : payTime.trim();
    }

    public String getTransactionId() {
        return transactionId;
    }

    public void setTransactionId(String transactionId) {
        this.transactionId = transactionId == null ? null : transactionId.trim();
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account == null ? null : account.trim();
    }

    public Integer getServerId() {
        return serverId;
    }

    public void setServerId(Integer serverId) {
        this.serverId = serverId;
    }

    public String getChrName() {
        return chrName;
    }

    public void setChrName(String chrName) {
        this.chrName = chrName == null ? null : chrName.trim();
    }

    public String getOrderType() {
        return orderType;
    }

    public void setOrderType(String orderType) {
        this.orderType = orderType == null ? null : orderType.trim();
    }

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName == null ? null : productName.trim();
    }

    public Integer getGiveVcoin() {
        return giveVcoin;
    }

    public void setGiveVcoin(Integer giveVcoin) {
        this.giveVcoin = giveVcoin;
    }

    public Integer getGiveVcb() {
        return giveVcb;
    }

    public void setGiveVcb(Integer giveVcb) {
        this.giveVcb = giveVcb;
    }

    public String getChannelProductId() {
        return channelProductId;
    }

    public void setChannelProductId(String channelProductId) {
        this.channelProductId = channelProductId == null ? null : channelProductId.trim();
    }

    public String getPrivateData() {
        return privateData;
    }

    public void setPrivateData(String privateData) {
        this.privateData = privateData == null ? null : privateData.trim();
    }

    public Date getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(Date orderTime) {
        this.orderTime = orderTime;
    }
}
package com.zkb.service;

import com.zkb.model.GameOrders;

import java.util.List;

/**
 * <h3>hzw</h3>
 * <p></p>
 *
 * @author : zkb
 * @date : 2021-01-21 19:37
 **/
public interface GameOrdersService {

    List<GameOrders> findGameOrders( int hs,int count);

    GameOrders selectBylast();

    int selectCount(String dbkey);

    void insertBatchOrder(List<GameOrders> list);
}
package com.zkb.service;

import com.zkb.model.GameAccounts;

import java.util.List;

/**
 * <h3>hzw</h3>
 * <p></p>
 *
 * @author : zkb
 * @date : 2021-01-21 18:22
 **/
public interface GameAccountService {

    List<GameAccounts> findGameAccounts(int hs);

    GameAccounts selectBylast();

    void insertBatchAccount(List<GameAccounts> list);
}
package com.zkb.service.impl;

import com.zkb.config.DatabaseContextHolder;
import com.zkb.mapper.GameAccountsMapper;
import com.zkb.model.GameAccounts;
import com.zkb.service.GameAccountService;
import com.zkb.util.DbUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <h3>hzw</h3>
 * <p></p>
 *
 * @author : zkb
 * @date : 2021-01-21 18:43
 **/
@Service
public class GameAccountServiceImpl implements GameAccountService {

    @Autowired
    GameAccountsMapper gameAccountsMapper;

    @Override
    public List<GameAccounts> findGameAccounts(int hs ) {
        // 指定数据源
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASIC);
        return gameAccountsMapper.findGameAccounts(hs);
    }

    @Override
    public GameAccounts selectBylast() {
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASE);
        return gameAccountsMapper.selectBylast();
    }

    @Override
    public void insertBatchAccount(List<GameAccounts> list) {
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASE);
        gameAccountsMapper.insertBatchAccount(list);
    }

}
package com.zkb.service.impl;

import com.zkb.config.DatabaseContextHolder;
import com.zkb.mapper.GameOrdersMapper;
import com.zkb.model.GameOrders;
import com.zkb.service.GameOrdersService;
import com.zkb.util.DbUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <h3>hzw</h3>
 * <p></p>
 *
 * @author : zkb
 * @date : 2021-01-21 19:38
 **/
@Service
public class GameOrdersServiceImpl implements GameOrdersService {

    @Autowired
    GameOrdersMapper gameOrdersMapper;
    @Override
    public List<GameOrders> findGameOrders(int hs,int count) {
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASIC);
        return gameOrdersMapper.findGameOrders(hs,count);
    }

    @Override
    public GameOrders selectBylast() {
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASIC);
        return gameOrdersMapper.selectBylast();
    }

    @Override
    public int selectCount(String dbkey) {
        DatabaseContextHolder.setDBKey(dbkey);
        return gameOrdersMapper.selectCount();
    }

    @Override
    public void insertBatchOrder(List<GameOrders> list) {
        DatabaseContextHolder.setDBKey(DbUtil.DB_BASE);
        gameOrdersMapper.insertBatchOrder(list);
    }
}
package com.zkb.util;

/**
 * 数据库数据源名称
 */
public class DbUtil {

    /**游戏数据库**/
    public static final String DB_BASIC = "ds_basic";   //游戏数据库
    /**数据库base**/
    public static final String DB_BASE = "ds_base";     //管理后台数据库

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zkb.mapper.GameAccountsMapper">
  <resultMap id="BaseResultMap" type="com.zkb.model.GameAccounts">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="account" jdbcType="VARCHAR" property="account" />
    <result column="bind_phone" jdbcType="VARCHAR" property="bindPhone" />
    <result column="password" jdbcType="VARCHAR" property="password" />
    <result column="distributors" jdbcType="VARCHAR" property="distributors" />
    <result column="dist_code" jdbcType="VARCHAR" property="distCode" />
    <result column="channel_id" jdbcType="INTEGER" property="channelId" />
    <result column="channel" jdbcType="VARCHAR" property="channel" />
    <result column="regdate" jdbcType="TIMESTAMP" property="regdate" />
    <result column="deviceId" jdbcType="VARCHAR" property="deviceid" />
    <result column="logintime" jdbcType="TIMESTAMP" property="logintime" />
    <result column="loginIp" jdbcType="VARCHAR" property="loginip" />
    <result column="loginKey" jdbcType="VARCHAR" property="loginkey" />
    <result column="flag" jdbcType="INTEGER" property="flag" />
  </resultMap>
  <sql id="Base_Column_List">
    id, account, bind_phone, password, distributors, dist_code, channel_id, channel, 
    regdate, deviceId, logintime, loginIp, loginKey, flag
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from accounts
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from accounts
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.zkb.model.GameAccounts">
    insert into accounts (id, account, bind_phone, 
      password, distributors, dist_code, 
      channel_id, channel, regdate, 
      deviceId, logintime, loginIp, 
      loginKey, flag)
    values (#{id,jdbcType=INTEGER}, #{account,jdbcType=VARCHAR}, #{bindPhone,jdbcType=VARCHAR}, 
      #{password,jdbcType=VARCHAR}, #{distributors,jdbcType=VARCHAR}, #{distCode,jdbcType=VARCHAR}, 
      #{channelId,jdbcType=INTEGER}, #{channel,jdbcType=VARCHAR}, #{regdate,jdbcType=TIMESTAMP}, 
      #{deviceid,jdbcType=VARCHAR}, #{logintime,jdbcType=TIMESTAMP}, #{loginip,jdbcType=VARCHAR}, 
      #{loginkey,jdbcType=VARCHAR}, #{flag,jdbcType=INTEGER})
  </insert>
  <insert id="insertSelective" parameterType="com.zkb.model.GameAccounts">
    insert into accounts
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="account != null">
        account,
      </if>
      <if test="bindPhone != null">
        bind_phone,
      </if>
      <if test="password != null">
        password,
      </if>
      <if test="distributors != null">
        distributors,
      </if>
      <if test="distCode != null">
        dist_code,
      </if>
      <if test="channelId != null">
        channel_id,
      </if>
      <if test="channel != null">
        channel,
      </if>
      <if test="regdate != null">
        regdate,
      </if>
      <if test="deviceid != null">
        deviceId,
      </if>
      <if test="logintime != null">
        logintime,
      </if>
      <if test="loginip != null">
        loginIp,
      </if>
      <if test="loginkey != null">
        loginKey,
      </if>
      <if test="flag != null">
        flag,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="account != null">
        #{account,jdbcType=VARCHAR},
      </if>
      <if test="bindPhone != null">
        #{bindPhone,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="distributors != null">
        #{distributors,jdbcType=VARCHAR},
      </if>
      <if test="distCode != null">
        #{distCode,jdbcType=VARCHAR},
      </if>
      <if test="channelId != null">
        #{channelId,jdbcType=INTEGER},
      </if>
      <if test="channel != null">
        #{channel,jdbcType=VARCHAR},
      </if>
      <if test="regdate != null">
        #{regdate,jdbcType=TIMESTAMP},
      </if>
      <if test="deviceid != null">
        #{deviceid,jdbcType=VARCHAR},
      </if>
      <if test="logintime != null">
        #{logintime,jdbcType=TIMESTAMP},
      </if>
      <if test="loginip != null">
        #{loginip,jdbcType=VARCHAR},
      </if>
      <if test="loginkey != null">
        #{loginkey,jdbcType=VARCHAR},
      </if>
      <if test="flag != null">
        #{flag,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.zkb.model.GameAccounts">
    update accounts
    <set>
      <if test="account != null">
        account = #{account,jdbcType=VARCHAR},
      </if>
      <if test="bindPhone != null">
        bind_phone = #{bindPhone,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="distributors != null">
        distributors = #{distributors,jdbcType=VARCHAR},
      </if>
      <if test="distCode != null">
        dist_code = #{distCode,jdbcType=VARCHAR},
      </if>
      <if test="channelId != null">
        channel_id = #{channelId,jdbcType=INTEGER},
      </if>
      <if test="channel != null">
        channel = #{channel,jdbcType=VARCHAR},
      </if>
      <if test="regdate != null">
        regdate = #{regdate,jdbcType=TIMESTAMP},
      </if>
      <if test="deviceid != null">
        deviceId = #{deviceid,jdbcType=VARCHAR},
      </if>
      <if test="logintime != null">
        logintime = #{logintime,jdbcType=TIMESTAMP},
      </if>
      <if test="loginip != null">
        loginIp = #{loginip,jdbcType=VARCHAR},
      </if>
      <if test="loginkey != null">
        loginKey = #{loginkey,jdbcType=VARCHAR},
      </if>
      <if test="flag != null">
        flag = #{flag,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.zkb.model.GameAccounts">
    update accounts
    set account = #{account,jdbcType=VARCHAR},
      bind_phone = #{bindPhone,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR},
      distributors = #{distributors,jdbcType=VARCHAR},
      dist_code = #{distCode,jdbcType=VARCHAR},
      channel_id = #{channelId,jdbcType=INTEGER},
      channel = #{channel,jdbcType=VARCHAR},
      regdate = #{regdate,jdbcType=TIMESTAMP},
      deviceId = #{deviceid,jdbcType=VARCHAR},
      logintime = #{logintime,jdbcType=TIMESTAMP},
      loginIp = #{loginip,jdbcType=VARCHAR},
      loginKey = #{loginkey,jdbcType=VARCHAR},
      flag = #{flag,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
  </update>


  <select id="findGameAccounts" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from accounts
    where id > #{hs,jdbcType=INTEGER}
  </select>

  <select id="selectBylast"  resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
     from accounts order by id DESC limit 1
  </select>


  <!-- 批量插入生成的兑换码 -->
  <insert id ="insertBatchAccount" parameterType="java.util.List" >
    insert into accounts (id, account, bind_phone,
    password, distributors, dist_code,
    channel_id, channel, regdate,
    deviceId, logintime, loginIp,
    loginKey, flag)
    values
    <foreach collection ="list" item="item" index= "index" separator =",">
      (#{item.id,jdbcType=INTEGER}, #{item.account,jdbcType=VARCHAR}, #{item.bindPhone,jdbcType=VARCHAR},
      #{item.password,jdbcType=VARCHAR}, #{item.distributors,jdbcType=VARCHAR}, #{item.distCode,jdbcType=VARCHAR},
      #{item.channelId,jdbcType=INTEGER}, #{item.channel,jdbcType=VARCHAR}, #{item.regdate,jdbcType=TIMESTAMP},
      #{item.deviceid,jdbcType=VARCHAR}, #{item.logintime,jdbcType=TIMESTAMP}, #{item.loginip,jdbcType=VARCHAR},
      #{item.loginkey,jdbcType=VARCHAR}, #{item.flag,jdbcType=INTEGER})
    </foreach >
  </insert >



</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zkb.mapper.GameOrdersMapper" >
  <resultMap id="BaseResultMap" type="com.zkb.model.GameOrders" >
    <id column="order_id" property="orderId" jdbcType="VARCHAR" />
    <result column="ticket_id" property="ticketId" jdbcType="VARCHAR" />
    <result column="distributors" property="distributors" jdbcType="VARCHAR" />
    <result column="dist_code" property="distCode" jdbcType="VARCHAR" />
    <result column="channel_id" property="channelId" jdbcType="VARCHAR" />
    <result column="amount" property="amount" jdbcType="REAL" />
    <result column="pay_status" property="payStatus" jdbcType="INTEGER" />
    <result column="pay_time" property="payTime" jdbcType="VARCHAR" />
    <result column="transaction_id" property="transactionId" jdbcType="VARCHAR" />
    <result column="account" property="account" jdbcType="VARCHAR" />
    <result column="server_id" property="serverId" jdbcType="INTEGER" />
    <result column="chr_name" property="chrName" jdbcType="VARCHAR" />
    <result column="order_type" property="orderType" jdbcType="VARCHAR" />
    <result column="product_id" property="productId" jdbcType="INTEGER" />
    <result column="product_name" property="productName" jdbcType="VARCHAR" />
    <result column="give_vcoin" property="giveVcoin" jdbcType="INTEGER" />
    <result column="give_vcb" property="giveVcb" jdbcType="INTEGER" />
    <result column="channel_product_id" property="channelProductId" jdbcType="VARCHAR" />
    <result column="private_data" property="privateData" jdbcType="VARCHAR" />
    <result column="order_time" property="orderTime" jdbcType="TIMESTAMP" />
  </resultMap>
  <sql id="Base_Column_List" >
    order_id, ticket_id, distributors, dist_code, channel_id, amount, pay_status, pay_time, 
    transaction_id, account, server_id, chr_name, order_type, product_id, product_name, 
    give_vcoin, give_vcb, channel_product_id, private_data, order_time
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
    select 
    <include refid="Base_Column_List" />
    from game_orders
    where order_id = #{orderId,jdbcType=VARCHAR}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
    delete from game_orders
    where order_id = #{orderId,jdbcType=VARCHAR}
  </delete>
  <insert id="insert" parameterType="com.zkb.model.GameOrders" >
    insert into game_orders (order_id, ticket_id, distributors, 
      dist_code, channel_id, amount, 
      pay_status, pay_time, transaction_id, 
      account, server_id, chr_name, 
      order_type, product_id, product_name, 
      give_vcoin, give_vcb, channel_product_id, 
      private_data, order_time)
    values (#{orderId,jdbcType=VARCHAR}, #{ticketId,jdbcType=VARCHAR}, #{distributors,jdbcType=VARCHAR}, 
      #{distCode,jdbcType=VARCHAR}, #{channelId,jdbcType=VARCHAR}, #{amount,jdbcType=REAL}, 
      #{payStatus,jdbcType=INTEGER}, #{payTime,jdbcType=VARCHAR}, #{transactionId,jdbcType=VARCHAR}, 
      #{account,jdbcType=VARCHAR}, #{serverId,jdbcType=INTEGER}, #{chrName,jdbcType=VARCHAR}, 
      #{orderType,jdbcType=VARCHAR}, #{productId,jdbcType=INTEGER}, #{productName,jdbcType=VARCHAR}, 
      #{giveVcoin,jdbcType=INTEGER}, #{giveVcb,jdbcType=INTEGER}, #{channelProductId,jdbcType=VARCHAR}, 
      #{privateData,jdbcType=VARCHAR}, #{orderTime,jdbcType=TIMESTAMP})
  </insert>
  <insert id="insertSelective" parameterType="com.zkb.model.GameOrders" >
    insert into game_orders
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="orderId != null" >
        order_id,
      </if>
      <if test="ticketId != null" >
        ticket_id,
      </if>
      <if test="distributors != null" >
        distributors,
      </if>
      <if test="distCode != null" >
        dist_code,
      </if>
      <if test="channelId != null" >
        channel_id,
      </if>
      <if test="amount != null" >
        amount,
      </if>
      <if test="payStatus != null" >
        pay_status,
      </if>
      <if test="payTime != null" >
        pay_time,
      </if>
      <if test="transactionId != null" >
        transaction_id,
      </if>
      <if test="account != null" >
        account,
      </if>
      <if test="serverId != null" >
        server_id,
      </if>
      <if test="chrName != null" >
        chr_name,
      </if>
      <if test="orderType != null" >
        order_type,
      </if>
      <if test="productId != null" >
        product_id,
      </if>
      <if test="productName != null" >
        product_name,
      </if>
      <if test="giveVcoin != null" >
        give_vcoin,
      </if>
      <if test="giveVcb != null" >
        give_vcb,
      </if>
      <if test="channelProductId != null" >
        channel_product_id,
      </if>
      <if test="privateData != null" >
        private_data,
      </if>
      <if test="orderTime != null" >
        order_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="orderId != null" >
        #{orderId,jdbcType=VARCHAR},
      </if>
      <if test="ticketId != null" >
        #{ticketId,jdbcType=VARCHAR},
      </if>
      <if test="distributors != null" >
        #{distributors,jdbcType=VARCHAR},
      </if>
      <if test="distCode != null" >
        #{distCode,jdbcType=VARCHAR},
      </if>
      <if test="channelId != null" >
        #{channelId,jdbcType=VARCHAR},
      </if>
      <if test="amount != null" >
        #{amount,jdbcType=REAL},
      </if>
      <if test="payStatus != null" >
        #{payStatus,jdbcType=INTEGER},
      </if>
      <if test="payTime != null" >
        #{payTime,jdbcType=VARCHAR},
      </if>
      <if test="transactionId != null" >
        #{transactionId,jdbcType=VARCHAR},
      </if>
      <if test="account != null" >
        #{account,jdbcType=VARCHAR},
      </if>
      <if test="serverId != null" >
        #{serverId,jdbcType=INTEGER},
      </if>
      <if test="chrName != null" >
        #{chrName,jdbcType=VARCHAR},
      </if>
      <if test="orderType != null" >
        #{orderType,jdbcType=VARCHAR},
      </if>
      <if test="productId != null" >
        #{productId,jdbcType=INTEGER},
      </if>
      <if test="productName != null" >
        #{productName,jdbcType=VARCHAR},
      </if>
      <if test="giveVcoin != null" >
        #{giveVcoin,jdbcType=INTEGER},
      </if>
      <if test="giveVcb != null" >
        #{giveVcb,jdbcType=INTEGER},
      </if>
      <if test="channelProductId != null" >
        #{channelProductId,jdbcType=VARCHAR},
      </if>
      <if test="privateData != null" >
        #{privateData,jdbcType=VARCHAR},
      </if>
      <if test="orderTime != null" >
        #{orderTime,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.zkb.model.GameOrders" >
    update game_orders
    <set >
      <if test="ticketId != null" >
        ticket_id = #{ticketId,jdbcType=VARCHAR},
      </if>
      <if test="distributors != null" >
        distributors = #{distributors,jdbcType=VARCHAR},
      </if>
      <if test="distCode != null" >
        dist_code = #{distCode,jdbcType=VARCHAR},
      </if>
      <if test="channelId != null" >
        channel_id = #{channelId,jdbcType=VARCHAR},
      </if>
      <if test="amount != null" >
        amount = #{amount,jdbcType=REAL},
      </if>
      <if test="payStatus != null" >
        pay_status = #{payStatus,jdbcType=INTEGER},
      </if>
      <if test="payTime != null" >
        pay_time = #{payTime,jdbcType=VARCHAR},
      </if>
      <if test="transactionId != null" >
        transaction_id = #{transactionId,jdbcType=VARCHAR},
      </if>
      <if test="account != null" >
        account = #{account,jdbcType=VARCHAR},
      </if>
      <if test="serverId != null" >
        server_id = #{serverId,jdbcType=INTEGER},
      </if>
      <if test="chrName != null" >
        chr_name = #{chrName,jdbcType=VARCHAR},
      </if>
      <if test="orderType != null" >
        order_type = #{orderType,jdbcType=VARCHAR},
      </if>
      <if test="productId != null" >
        product_id = #{productId,jdbcType=INTEGER},
      </if>
      <if test="productName != null" >
        product_name = #{productName,jdbcType=VARCHAR},
      </if>
      <if test="giveVcoin != null" >
        give_vcoin = #{giveVcoin,jdbcType=INTEGER},
      </if>
      <if test="giveVcb != null" >
        give_vcb = #{giveVcb,jdbcType=INTEGER},
      </if>
      <if test="channelProductId != null" >
        channel_product_id = #{channelProductId,jdbcType=VARCHAR},
      </if>
      <if test="privateData != null" >
        private_data = #{privateData,jdbcType=VARCHAR},
      </if>
      <if test="orderTime != null" >
        order_time = #{orderTime,jdbcType=TIMESTAMP},
      </if>
    </set>
    where order_id = #{orderId,jdbcType=VARCHAR}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.zkb.model.GameOrders" >
    update game_orders
    set ticket_id = #{ticketId,jdbcType=VARCHAR},
      distributors = #{distributors,jdbcType=VARCHAR},
      dist_code = #{distCode,jdbcType=VARCHAR},
      channel_id = #{channelId,jdbcType=VARCHAR},
      amount = #{amount,jdbcType=REAL},
      pay_status = #{payStatus,jdbcType=INTEGER},
      pay_time = #{payTime,jdbcType=VARCHAR},
      transaction_id = #{transactionId,jdbcType=VARCHAR},
      account = #{account,jdbcType=VARCHAR},
      server_id = #{serverId,jdbcType=INTEGER},
      chr_name = #{chrName,jdbcType=VARCHAR},
      order_type = #{orderType,jdbcType=VARCHAR},
      product_id = #{productId,jdbcType=INTEGER},
      product_name = #{productName,jdbcType=VARCHAR},
      give_vcoin = #{giveVcoin,jdbcType=INTEGER},
      give_vcb = #{giveVcb,jdbcType=INTEGER},
      channel_product_id = #{channelProductId,jdbcType=VARCHAR},
      private_data = #{privateData,jdbcType=VARCHAR},
      order_time = #{orderTime,jdbcType=TIMESTAMP}
    where order_id = #{orderId,jdbcType=VARCHAR}
  </update>


  <select id="findGameOrders"  resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from game_orders
    limit  #{hs,jdbcType=INTEGER},#{count,jdbcType=INTEGER}
  </select>

  <select id="selectBylast"  resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from game_orders order by id DESC limit 1
  </select>

  <select id="selectCount"  resultType="java.lang.Integer">
    select
    count(*)
    from game_orders
  </select>


  <insert id ="insertBatchOrder" parameterType="java.util.List" >
    insert into game_orders (order_id, ticket_id, distributors,
    dist_code, channel_id, amount,
    pay_status, pay_time, transaction_id,
    account, server_id, chr_name,
    order_type, product_id, product_name,
    give_vcoin, give_vcb, channel_product_id,
    private_data, order_time)
    values
    <foreach collection ="list" item="item" index= "index" separator =",">
      (#{item.orderId,jdbcType=VARCHAR}, #{item.ticketId,jdbcType=VARCHAR}, #{item.distributors,jdbcType=VARCHAR},
      #{item.distCode,jdbcType=VARCHAR}, #{item.channelId,jdbcType=VARCHAR}, #{item.amount,jdbcType=REAL},
      #{item.payStatus,jdbcType=INTEGER}, #{item.payTime,jdbcType=VARCHAR}, #{item.transactionId,jdbcType=VARCHAR},
      #{item.account,jdbcType=VARCHAR}, #{item.serverId,jdbcType=INTEGER}, #{item.chrName,jdbcType=VARCHAR},
      #{item.orderType,jdbcType=VARCHAR}, #{item.productId,jdbcType=INTEGER}, #{item.productName,jdbcType=VARCHAR},
      #{item.giveVcoin,jdbcType=INTEGER}, #{item.giveVcb,jdbcType=INTEGER}, #{item.channelProductId,jdbcType=VARCHAR},
      #{item.privateData,jdbcType=VARCHAR}, #{item.orderTime,jdbcType=TIMESTAMP})
    </foreach >
  </insert >






</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>springBootData</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath />
    </parent>

    <dependencies>
        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>

</project>

到此算是实现了一整个完整的数据源切换的demo    

每次切换都需要  来制度自己所要切换到的数据源

// 指定数据源
DatabaseContextHolder.setDBKey(DbUtil.DB_BASIC);

如果有加事务的话,一定要在开启事务之前切换数据源,进入事务之后切换数据源是无效的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斗码士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值