#spring-boot #datasource #jdbctemplate
Вопрос:
Не могли бы вы, пожалуйста, помочь мне создать мультисоединение datasource
внутри springboot
? У меня будет много конфигураций баз данных, зарегистрированных в другой основной базе данных. Я не могу использовать источник данных, управляемый .properties
spring, потому что у меня будет много настроек для подключения.
В конце концов, мне нужно JdbcTemplate
отказаться от использования многих процедур.
Как создать фабрику источников данных весной для использования с JdbcTemplate? Я пробовал некоторые коды, но безуспешно;
Фабрика Соединений
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class ConfigDataSourceDynamic {
private static Map<String,DataSource> mapDataSource;
private JdbcTemplate jdbcTemplate;
@PostConstruct
public void init(){
mapDataSource = new HashMap<String,DataSource>();
}
private DataSource createNewConnection(String nameConfig, String username, String password, String url, String driver){
DataSource dataSource = DataSourceBuilder
.create()
.username(username)
.password(password)
.url(url)
.driverClassName(driver)
.build();
mapDataSource.put(nameConfig, dataSource );
return dataSource;
}
private DataSource getDataSource(String nameConfig, String nameConfig, String username, String password, String url, String driver){
if( !mapDataSource.containsKey(nameConfig, username, password,url, driver) )
return createNewConnection(nameConfig);
DataSource dataSource = mapDataSource.get(nameConfig);
try{
dataSource.getConnection().close();
}catch(Exception e){
e.printStackTrace();
}
return createNewConnection(tnsName);
}
public JdbcTemplate getJdbcTemplateDynamic(String nameConfig, String username, String password, String url, String driver) throws ApiReturnException{
return new JdbcTemplate(getDataSource(nameConfig, username, password,url, driver));
}
}
Выполнение кода
@Autowired
private ConfigDataSourceDynamic configDataSourceDynamic;
public Object testeMultiDBConfig() throws ApiReturnException{
String nameConfig = // from table of configuration
String username = // from table of configuration
String password = // from table of configuration
String url = // from table of configuration
String driver = // from table of configuration
JdbcTemplate jdbcTemplateTeste = configDataSourceDynamic.getJdbcTemplateDynamic(nameConfig, username, password,url, driver);
List<Map<String, Object>> a = jdbcTemplateTeste.queryForList("select * from TESTE");
a.forEach(System.out::println);
return a;
}
Я получил ошибки после 8,9 успешных подключений:
oracle.net.ns.NetException: Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found
at oracle.net.ns.NSProtocolNIO.negotiateConnection(NSProtocolNIO.java:284) NSProtocolNIO.java:284
at oracle.net.ns.NSProtocol.connect(NSProtocol.java:340) NSProtocol.java:340
at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1596) T4CConnection.java:1596
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:588) T4CConnection.java:588
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:793) PhysicalConnection.java:793
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:57) T4CDriverExtension.java:57
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:747) OracleDriver.java:747
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:562) OracleDriver.java:562
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) DriverDataSource.java:138
Комментарии:
1. Я думаю, что это не весенняя проблема. Это проблема с сетевым подключением. Возможно, порты являются незаконными или порты заблокированы на стороне базы данных
2. @Alex Я получил 8,9 последовательных соединений, а затем получил ошибку. Есть ли другой способ создать фабрику соединений в springboot, чтобы использовать JdbcTemplate без источника данных bean?
3. Всегда ли параметры подключения одинаковы?
4. Нет, к сожалению, все параметры подключения являются определенной таблицей в базе данных, в зависимости от подключения, которое я собираюсь подключить и вызвать некоторые процедуры в определенной базе данных.
Ответ №1:
У меня есть лучшее решение 🙂 Я опубликую здесь…
Использование HikariConfig для управления пулом подключений
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class ConfigDataSourceDynamic {
private static Map<String,HikariDataSource> mapDataSource;
@PostConstruct
public void init(){
mapDataSource = new ConcurrentHashMap<String,HikariDataSource>();
}
private synchronized HikariDataSource createNewConnection(String tnsName, String username, String password, String url, String driver){
HikariConfig configHikari = new HikariConfig();
configHikari.setUsername(username);
configHikari.setPassword(password);
configHikari.setJdbcUrl(url);
configHikari.setDriverClassName(driver);
HikariDataSource dataSource = new HikariDataSource(configHikari);
mapDataSource.put(tnsName, dataSource );
return dataSource;
}
private synchronized HikariDataSource getDataSource(String tnsName, String username, String password, String url, String driver){
if( !mapDataSource.containsKey(tnsName) )
return createNewConnection(tnsName, username, password,url, driver);
HikariDataSource dataSource = mapDataSource.get(tnsName);
try{
if(dataSource.isClosed()){
return createNewConnection(tnsName);
}else{
return dataSource;
}
}catch(Exception e){
e.printStackTrace();
}
return createNewConnection(tnsName);
}
public JdbcTemplate getJdbcTemplateDynamic(String tnsName, String username, String password, String url, String driver){
return new JdbcTemplate(getDataSource(tnsName, username, password,url, driver));
}
}
Выполняется
@Autowired
private ConfigDataSourceDynamic configDataSourceDynamic;
public void testeMultiDBConfig() throws ApiReturnException{
String nameConfig = // from table of configuration
String username = // from table of configuration
String password = // from table of configuration
String url = // from table of configuration
String driver = // from table of configuration
JdbcTemplate jdbcTemplateTeste = configDataSourceDynamic
.getJdbcTemplateDynamic(nameConfig, username, password,url, driver);
for (int i = 0; i < 500; i ) { // so many requests to over test
jdbcTemplateTeste.execute("INSERT INTO TABLE1 ( COL ) VALUES ( 'VALUE')");
List<Map<String, Object>> result = jdbcTemplateTeste.queryForList("SELECT * FROM TABLE1");
result.forEach(System.out::println);
jdbcTemplateTeste.execute("DELETE FROM TABLE1");
}