package com.mogujie.trade.db; import org.springframework.jdbc.datasource.AbstractDataSource; import org.springframework.util.Assert; import javax.sql.DataSource; import java.io.Closeable; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; /** * @author by jiuru on 16/7/14. */ public class ReadWriteSplittingDataSource extends AbstractDataSource implements DataSource, Closeable { private final String name; private final DataSource masterDataSource; private final DataSource slaveDataSource; public ReadWriteSplittingDataSource(String name, DataSource masterDataSource, DataSource slaveDataSource) { this.name = name; this.masterDataSource = masterDataSource; this.slaveDataSource = slaveDataSource; Assert.isTrue(masterDataSource != slaveDataSource || masterDataSource != null, "masterDataSource and slaveDataSource can't be both null!"); } @Override public Connection getConnection() throws SQLException { return this.determineTargetDataSource().getConnection(); } public DataSource getSlaveDataSource() { return slaveDataSource; } private DataSource determineTargetDataSource() { if (slaveDataSource == null) { return masterDataSource; } if (this.isInTransaction()) { return masterDataSource; } return ReadWriteSplittingContext.isMaster() ? masterDataSource : slaveDataSource; } private boolean isInTransaction() { return RoutingDataSourceTransactionContext.getCurTransactionDataSource() != null; } @Override public Connection getConnection(String username, String password) throws SQLException { return this.determineTargetDataSource().getConnection(username, password); } public String getName() { return this.name; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ReadWriteSplittingDataSource ["); if (name != null) { builder.append("name=").append(name).append(", "); } if (masterDataSource != null) { builder.append("masterDataSource=").append(masterDataSource).append(", "); } if (slaveDataSource != null) { builder.append("slaveDataSource=").append(slaveDataSource); } builder.append("]"); return builder.toString(); } @Override public void close() throws IOException { if (this.masterDataSource != null) { if (masterDataSource instanceof AutoCloseable) { try { ((AutoCloseable) masterDataSource).close(); } catch (Exception ignore) { } } } if (this.slaveDataSource != null) { if (slaveDataSource instanceof AutoCloseable) { try { ((AutoCloseable) slaveDataSource).close(); } catch (Exception ignore) { } } } } }