|
@@ -14,23 +14,29 @@
|
|
|
* limitations under the License.
|
|
|
*/
|
|
|
|
|
|
-package org.hsweb.web.service.impl.datasource;
|
|
|
+package org.hsweb.web.datasource.dynamic;
|
|
|
|
|
|
+import com.atomikos.jdbc.AtomikosDataSourceBean;
|
|
|
+import com.atomikos.jdbc.AtomikosSQLException;
|
|
|
import org.hsweb.concurrent.lock.LockFactory;
|
|
|
-import org.hsweb.ezorm.executor.SqlExecutor;
|
|
|
import org.hsweb.web.bean.po.datasource.DataSource;
|
|
|
import org.hsweb.web.core.datasource.DynamicDataSource;
|
|
|
import org.hsweb.web.core.exception.NotFoundException;
|
|
|
import org.hsweb.web.service.datasource.DataSourceService;
|
|
|
import org.hsweb.web.service.datasource.DynamicDataSourceService;
|
|
|
-import org.hsweb.web.service.impl.basic.SqlExecutorService;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.PlatformTransactionManager;
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
+import javax.annotation.PreDestroy;
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.io.Closeable;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.Properties;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.ConcurrentMap;
|
|
|
import java.util.concurrent.locks.ReadWriteLock;
|
|
@@ -38,14 +44,21 @@ import java.util.concurrent.locks.ReadWriteLock;
|
|
|
@Service("dynamicDataSourceService")
|
|
|
public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
|
|
|
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
|
@Resource
|
|
|
private DataSourceService dataSourceService;
|
|
|
|
|
|
@Autowired(required = false)
|
|
|
- private DynamicDataSource dynamicDataSource;
|
|
|
+ @Qualifier("atomikosDataSourceBean")
|
|
|
+ private AtomikosDataSourceBean atomikosDataSourceBean;
|
|
|
|
|
|
@Autowired
|
|
|
private LockFactory lockFactory;
|
|
|
+// @Resource
|
|
|
+// private DynamicDeployBeans dynamicDeployBeans;
|
|
|
+
|
|
|
+// @Autowired
|
|
|
+// ApplicationContext applicationContext;
|
|
|
|
|
|
private ConcurrentMap<String, CacheInfo> cache = new ConcurrentHashMap<>();
|
|
|
|
|
@@ -54,13 +67,23 @@ public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
return getCache(id).getDataSource();
|
|
|
}
|
|
|
|
|
|
- public PlatformTransactionManager getTransactionManager(String id) {
|
|
|
- return getCache(id).getTransactionManager();
|
|
|
+ @Override
|
|
|
+ @PreDestroy
|
|
|
+ public void destroyAll() throws Exception {
|
|
|
+ cache.values().stream().map(CacheInfo::getDataSource).forEach(this::closeDataSource);
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public SqlExecutor getSqlExecutor(String id) {
|
|
|
- return getCache(id).getSqlExecutor();
|
|
|
+ protected void closeDataSource(javax.sql.DataSource ds) {
|
|
|
+ if (ds instanceof AtomikosDataSourceBean) {
|
|
|
+ ((AtomikosDataSourceBean) ds).close();
|
|
|
+ }
|
|
|
+ if (ds instanceof Closeable) {
|
|
|
+ try {
|
|
|
+ ((Closeable) ds).close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("close datasource error", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
protected CacheInfo getCache(String id) {
|
|
@@ -82,9 +105,13 @@ public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
//加载datasource到缓存
|
|
|
readWriteLock.writeLock().tryLock();
|
|
|
try {
|
|
|
- javax.sql.DataSource dataSource = dataSourceService.createDataSource(id);
|
|
|
+ javax.sql.DataSource dataSource = createDataSource(old);
|
|
|
+
|
|
|
CacheInfo cacheInfo = new CacheInfo(old.getHash(), dataSource);
|
|
|
- cache.put(id, cacheInfo);
|
|
|
+ CacheInfo oldCache = cache.put(id, cacheInfo);
|
|
|
+ if (oldCache != null) {
|
|
|
+ closeDataSource(oldCache.getDataSource());
|
|
|
+ }
|
|
|
return cacheInfo;
|
|
|
} finally {
|
|
|
readWriteLock.writeLock().unlock();
|
|
@@ -94,10 +121,45 @@ public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private DataSourceProperties properties;
|
|
|
+
|
|
|
+ protected javax.sql.DataSource createDataSource(DataSource dataSource) {
|
|
|
+ AtomikosDataSourceBean dataSourceBean = new AtomikosDataSourceBean();
|
|
|
+ Properties xaProperties = new Properties();
|
|
|
+ if (dataSource.getProperties() != null)
|
|
|
+ xaProperties.putAll(dataSource.getProperties());
|
|
|
+ if (dataSource.getDriver().contains("mysql")) {
|
|
|
+ dataSourceBean.setXaDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
|
|
|
+ xaProperties.put("pinGlobalTxToPhysicalConnection", true);
|
|
|
+ xaProperties.put("user", dataSource.getUsername());
|
|
|
+ xaProperties.put("password", dataSource.getPassword());
|
|
|
+ xaProperties.put("url", dataSource.getUrl());
|
|
|
+ } else {
|
|
|
+ dataSourceBean.setXaDataSourceClassName(properties.getXa().getDataSourceClassName());
|
|
|
+ xaProperties.put("username", dataSource.getUsername());
|
|
|
+ xaProperties.put("password", dataSource.getPassword());
|
|
|
+ xaProperties.put("url", dataSource.getUrl());
|
|
|
+ xaProperties.put("driverClassName", dataSource.getDriver());
|
|
|
+ }
|
|
|
+ dataSourceBean.setXaProperties(xaProperties);
|
|
|
+ dataSourceBean.setUniqueResourceName("ds_" + dataSource.getId());
|
|
|
+ dataSourceBean.setMaxPoolSize(200);
|
|
|
+ dataSourceBean.setMinPoolSize(5);
|
|
|
+ dataSourceBean.setTestQuery(dataSource.getTestSql());
|
|
|
+ dataSourceBean.setBorrowConnectionTimeout(60);
|
|
|
+ try {
|
|
|
+ dataSourceBean.init();
|
|
|
+ } catch (AtomikosSQLException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ return dataSourceBean;
|
|
|
+ }
|
|
|
+
|
|
|
@PostConstruct
|
|
|
public void init() {
|
|
|
- if (null != dynamicDataSource)
|
|
|
- ((DynamicDataSourceImpl) dynamicDataSource).setDynamicDataSourceService(this);
|
|
|
+ if (null != atomikosDataSourceBean)
|
|
|
+ ((DynamicXaDataSourceImpl) atomikosDataSourceBean.getXaDataSource()).setDynamicDataSourceService(this);
|
|
|
}
|
|
|
|
|
|
class CacheInfo {
|
|
@@ -105,15 +167,9 @@ public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
|
|
|
javax.sql.DataSource dataSource;
|
|
|
|
|
|
- PlatformTransactionManager transactionManager;
|
|
|
-
|
|
|
- SqlExecutor sqlExecutor;
|
|
|
-
|
|
|
public CacheInfo(int hash, javax.sql.DataSource dataSource) {
|
|
|
this.hash = hash;
|
|
|
this.dataSource = dataSource;
|
|
|
- sqlExecutor = new SqlExecutorService().setDataSource(dataSource);
|
|
|
- transactionManager = new DataSourceTransactionManager(dataSource);
|
|
|
}
|
|
|
|
|
|
public int getHash() {
|
|
@@ -123,14 +179,6 @@ public class DynamicDataSourceServiceImpl implements DynamicDataSourceService {
|
|
|
public javax.sql.DataSource getDataSource() {
|
|
|
return dataSource;
|
|
|
}
|
|
|
-
|
|
|
- public SqlExecutor getSqlExecutor() {
|
|
|
- return sqlExecutor;
|
|
|
- }
|
|
|
-
|
|
|
- public PlatformTransactionManager getTransactionManager() {
|
|
|
- return transactionManager;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
}
|