package io.mycat.backend.jdbc;
import io.mycat.backend.PhysicalDatasource;
import io.mycat.backend.heartbeat.DBHeartbeat;
import io.mycat.net.ConnectIdGenerator;
import io.mycat.server.config.loader.LocalLoader;
import io.mycat.server.config.node.DBHostConfig;
import io.mycat.server.config.node.DataHostConfig;
import io.mycat.server.config.node.JdbcDriver;
import io.mycat.server.executors.ResponseHandler;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JDBCDatasource extends PhysicalDatasource {
public static final Logger logger = LoggerFactory.getLogger(JDBCDatasource.class);
private static Map<String, JdbcDriver> jdbcDriverConfig = null;
static { // 最多也就3,4个数据库,一次性加载驱动类
jdbcDriverConfig = LocalLoader.loadJdbcDriverConfig();
if(jdbcDriverConfig != null && jdbcDriverConfig.size() > 0){
for(String key : jdbcDriverConfig.keySet()){
JdbcDriver driver = jdbcDriverConfig.get(key);
if(driver != null && StringUtils.isNotBlank(driver.getClassName())){
try {
Class.forName(driver.getClassName());
} catch (ClassNotFoundException e) {
logger.error("Class.forName load jdbcDriver for "+key+" error: " + e.getMessage());
}
}else{
logger.error(" driver for " + key + " is not exist or className has no value,"
+ " please check jdbcDriver-config element in mycat.xml.");
}
}
}
}
public JDBCDatasource(DBHostConfig config, DataHostConfig hostConfig,
boolean isReadNode) {
super(config, hostConfig, isReadNode);
}
@Override
public DBHeartbeat createHeartBeat() {
return new JDBCHeartbeat(this);
}
@Override
public void createNewConnection(ResponseHandler handler, String schema)
throws IOException {
DBHostConfig cfg = getConfig();
JDBCConnection c = null;
try {
// TODO: 这里需要实现连继池
Connection con = getConnection();
c = new JDBCConnection();
c.setHost(cfg.getIp());
c.setPort(cfg.getPort());
c.setPool(this);
c.setSchema(schema);
c.setDbType(cfg.getDbType());
c.setId(ConnectIdGenerator.getINSTNCE().getId()); // 复用mysql的Backend的ID,需要在process中存储
// c.setIdleTimeout(pool.getConfig().getIdleTimeout());
c.setCon(con);
// notify handler
handler.connectionAcquired(c);
} catch (Exception e) {
handler.connectionError(e, c);
}
}
Connection getConnection() throws SQLException {
DBHostConfig cfg = getConfig();
Enumeration<Driver> drivers = DriverManager.getDrivers();
Driver d = drivers.nextElement();
d.getClass().getName();
Connection connection = DriverManager.getConnection(cfg.getUrl(),
cfg.getUser(), cfg.getPassword());
String initSql = getHostConfig().getConnectionInitSql();
if (StringUtils.isNotBlank(initSql)) {
try (Statement statement = connection.createStatement()){
statement.execute(initSql);
} catch(SQLException e) {
logger.warn(" getConnection error: " + e.getMessage());
}
}
return connection;
}
/**
* 根据 dbType 获取 JdbcDriver
* @param dbType mysql
* @return JdbcDriver: {'mysql':'com.mysql.jdbc.Driver'}
*/
public static JdbcDriver getJdbcDriverBydbType(String dbType){
if(StringUtils.isNotBlank(dbType)){
return jdbcDriverConfig.get(dbType.toLowerCase()); // 获取对应 dbType 的 JdbcDriver
}
return null;
}
public static Map<String, JdbcDriver> getJdbcDriverConfig() {
return jdbcDriverConfig;
}
public static void setJdbcDriverConfig(Map<String, JdbcDriver> jdbcDriverConfig) {
JDBCDatasource.jdbcDriverConfig = jdbcDriverConfig;
}
}