xpc
2024-02-27 d552ef9f4ea7ea8500f40195517387a6ab865f9a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
package com.product.datasource.connection;
 
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.google.common.collect.Maps;
import com.product.common.lang.StringUtils;
import com.product.core.config.Global;
import com.product.core.exception.BaseException;
import com.product.datasource.config.DataBaseType;
import com.product.datasource.config.ErrorCode;
import com.product.datasource.entity.DataBaseEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import javax.sql.DataSource;
import java.sql.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
/**
 * @Author cheng
 * @Date 2022/2/5 17:05
 * @Desc
 */
public class ConnectionManager {
 
    static Logger log = LoggerFactory.getLogger(ConnectionManager.class);
 
    private static final Map<String, DruidDataSource> DB_DRUID_DATA_SOURCE_MAP = new ConcurrentHashMap<>();
 
    public static void main(String[] args) {
        DataBaseEntity DataBaseEntity = new DataBaseEntity(DataBaseType.MYSQL.getValue());
        DataBaseEntity.setDbName("product_db_v2.0.0");
        DataBaseEntity.setUserName("root");
        DataBaseEntity.setIp("127.0.0.1");
        DataBaseEntity.setPassWord("root123");
        DataBaseEntity.setPort("3306");
        DataBaseEntity.setCustomParams("&serverTimezone=Asia/Shanghai");
        getConnection(DataBaseEntity);
    }
 
    /**
     * 获取系统连接
     *
     * @return
     */
    public static Connection getSystemConnection() throws BaseException {
        String url = Global.getSystemConfig("data.source.url", "");
        String userName = Global.getSystemConfig("data.source.user", "");
        String userPassword = Global.getSystemConfig("data.source.password", "");
        //批量提交参数是否开启
        if (url.indexOf("rewriteBatchedStatements=true") == -1) {
            url += "&rewriteBatchedStatements=true";
        }
        DataBaseEntity DataBaseEntity = new DataBaseEntity(DataBaseType.MYSQL.getValue());
        DataBaseEntity.setUserName(userName);
        DataBaseEntity.setPassWord(userPassword);
        return getConnection(url, DataBaseEntity);
    }
 
 
    /**
     * 获取连接
     *
     * @param dbe
     * @return
     * @throws BaseException
     */
    public static Connection getConnection(DataBaseEntity dbe) throws BaseException {
 
        try {
            if (dbe.getDataBaseType() == null) {
                throw new BaseException(ErrorCode.UNKNOWN_DATABASE_TYPE);
            }
            //装载驱动
            Class.forName(dbe.getDataBaseType().getDriver());
            if (DataBaseType.MYSQL.equals(dbe.getDataBaseType())) {
                // MYSQL
                return getMysqlConnection(dbe);
            } else if (DataBaseType.ORACLE.equals(dbe.getDataBaseType())) {
                // ORACLE
                return getOracleConnection(dbe);
            } else if (DataBaseType.SQLSERVER.equals(dbe.getDataBaseType())) {
                // SQLSERVER
                return getSqlServerConnection(dbe);
            } else if (DataBaseType.INFORMIX.equals(dbe.getDataBaseType())) {
                // INFORMIX
                return getInformixConnection(dbe);
            } else if (DataBaseType.PSQL.equals(dbe.getDataBaseType())) {
                return getPSQLConnection(dbe);
            }
            throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
        } catch (BaseException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
        }
    }
 
    public static Connection getPSQLConnection(DataBaseEntity dbe) {
        String templateUrl = "jdbc:postgresql://%s:%s/%s%s";
        //替换URL模板
        String url = String.format(templateUrl, dbe.getIp(), dbe.getPort(), dbe.getDbName(), dbe.getCustomParams());
        return getConnection(url, dbe);
    }
 
    public static long getConnectionSystemTime(Connection connection, DataBaseType dbType) throws BaseException {
        String queryTimeSql;
        if (DataBaseType.MYSQL.equals(dbType)) {
            queryTimeSql = "select current_timestamp(3) `timestamp` ";
        } else if (DataBaseType.ORACLE.equals(dbType)) {
            queryTimeSql = "select systimestamp  as timestamp from dual";
        }
//        else if (DriverTypeEnum.SqlServer.equals(dbType)) {
//            queryTimeSql = "SELECT CONVERT(BIGINT,DATEDIFF(MI,'1970-01-01 00:00:00.000', GETUTCDATE())) * 60000 + DATEPART(S,GETUTCDATE()) * 1000 + DATEPART(MS, GETUTCDATE()) as timestamp";
//        } else if (DriverTypeEnum.Informix.equals(dbType)) {
//            queryTimeSql = "select current as timestamp from sysmaster:sysshmvals";
//        }
        else {
            throw new BaseException(ErrorCode.GET_CONNECTION_TIME_FAIL);
        }
        try (PreparedStatement pst = connection.prepareStatement(queryTimeSql); ResultSet resultSet = pst.executeQuery();) {
            while (resultSet.next()) {
                final Object timestamp = resultSet.getObject("timestamp");
                if (timestamp != null) {
                    if (timestamp instanceof Time) {
                        return ((Time) timestamp).getTime();
                    } else if (timestamp instanceof Timestamp) {
                        return ((Timestamp) timestamp).getTime();
                    } else {
                        return resultSet.getTimestamp("timestamp").getTime();
                    }
                }
                return resultSet.getLong("timestamp");
            }
            throw new BaseException(ErrorCode.GET_CONNECTION_TIME_FAIL);
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(ErrorCode.GET_CONNECTION_TIME_FAIL);
        }
    }
 
 
    /**
     * 获取MySql连接
     *
     * @param dbe
     * @return
     * @throws SQLException
     */
    private static Connection getMysqlConnection(DataBaseEntity dbe) {
        String templateUrl = "jdbc:mysql://%s:%s/%s%s";
        //替换URL模板
        String url = String.format(templateUrl, dbe.getIp(), dbe.getPort(), dbe.getDbName(), dbe.getCustomParams());
        return getConnection(url, dbe);
    }
 
    /**
     * 获取Sql Server连接
     *
     * @param dbe
     * @return
     * @throws SQLException
     */
    private static Connection getSqlServerConnection(DataBaseEntity dbe) {
        String dbInstance = dbe.getDbInstance();
        String url;
        if (StringUtils.isEmpty(dbInstance)) {
            url = String.format("jdbc:sqlserver://%s:%s;databaseName=%s;", dbe.getIp(), dbe.getPort(), dbe.getDbName());
        } else {
            // 有实例名
            url = String.format("jdbc:sqlserver://%s:%s;instanceName=%s;databaseName=%s;", dbe.getIp(), dbe.getPort(), dbe.getDbInstance(), dbe.getDbName());
        }
        return getConnection(url, dbe);
    }
 
    /**
     * 获取Oracle连接
     *
     * @param dbe
     * @return
     * @throws SQLException
     */
    private static Connection getOracleConnection(DataBaseEntity dbe) {
        String url;
        String[] params = {dbe.getIp(), dbe.getPort(), null};
        if (!StringUtils.isEmpty(dbe.getSid())) {
            url = String.format("jdbc:oracle:thin:@%s:%s:%s", dbe.getIp(), dbe.getPort(), dbe.getSid());
            params[2] = dbe.getSid();
        } else if (!StringUtils.isEmpty(dbe.getServerName())) {
            url = String.format("jdbc:oracle:thin:@//%s:%s/%s", dbe.getIp(), dbe.getPort(), dbe.getServerName());
            params[2] = dbe.getServerName();
        } else {
            throw new BaseException(ErrorCode.GET_ORACLE_SID_SERVERNAME_EMPTY);
        }
        Boolean enabling = Global.getPropertyToBoolean("data.system.oracle.connection-pool.enabling", "false");
        if (enabling) {
            synchronized (url.intern()) {
                DruidDataSource druidDataSource = DB_DRUID_DATA_SOURCE_MAP.get(ArrayUtil.join(params, ","));
                if (druidDataSource == null || druidDataSource.isClosed()) {
                    druidDataSource = new DruidDataSource();
                    druidDataSource.setUrl(url);
                    druidDataSource.setUsername(dbe.getUserName());
                    druidDataSource.setPassword(dbe.getPassWord());
                    // 初始化时建立物理连接的个数
                    druidDataSource.setInitialSize(getProperty("data.system.oracle.connection-pool.initial-size", 20));
                    // 最大活动连接数
                    druidDataSource.setMaxActive(getProperty("data.system.oracle.connection-pool.max-active", 100));
                    // 最小空闲连接数
                    druidDataSource.setMinIdle(getProperty("data.system.oracle.connection-pool.min-idle", 30));
                    // 校验查询语句
                    druidDataSource.setValidationQuery(dbe.getDataBaseType().getValidationQuery());
                    // 当连接空闲时是否测试连接有效性
                    druidDataSource.setTestWhileIdle(true);
                    // 两次空闲连接清除之间的时间间隔 12小时
                    druidDataSource.setTimeBetweenEvictionRunsMillis(43200000L);
                    druidDataSource.setMaxWait(60000L);
                    druidDataSource.setPoolPreparedStatements(true);
                    druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(100);
                    druidDataSource.setRemoveAbandoned(true);
                    //半小时强制归还连接
                    druidDataSource.setRemoveAbandonedTimeout(60 * 30);
                    DB_DRUID_DATA_SOURCE_MAP.put(ArrayUtil.join(params, ","), druidDataSource);
                }
                try {
                    //获获取连接
                    Connection connection = druidDataSource.getConnection();
                    //测试连接
                    if (!connectionValidity(connection, dbe.getDataBaseType())) {
                        throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
                    }
                    return connection;
                } catch (BaseException e) {
                    throw e;
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("获取链接失败", e);
                    log.error(url);
                    throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
                }
            }
        }
        return getConnection(url, dbe);
    }
 
    private static int getProperty(String key, int defaultValue) {
        String systemConfig = Global.getSystemConfig(key, defaultValue + "");
        if (!NumberUtil.isNumber(systemConfig)) {
            return defaultValue;
        }
        return NumberUtil.parseInt(systemConfig);
    }
 
    /**
     * 获取Informix 连接
     *
     * @param dbe
     * @return
     * @throws SQLException
     */
    private static Connection getInformixConnection(DataBaseEntity dbe) throws BaseException {
        String url = String.format("jdbc:informix-sqli://%s:%s/%s:INFORMIXSERVER=%s;%s", dbe.getIp(), dbe.getPort(), dbe.getDbName(), dbe.getDbInstance(), dbe.getCustomParams());
        return getConnection(url, dbe);
    }
 
    /**
     * 获取连接
     *
     * @param url jdbc连接url
     * @param dbe 数据库基本数据
     * @return
     * @throws SQLException
     */
    private static Connection getConnection(String url, DataBaseEntity dbe) throws BaseException {
        try {
            //获获取连接
            Connection connection = DriverManager.getConnection(url, dbe.getUserName(), dbe.getPassWord());
            //测试连接
            if (!connectionValidity(connection, dbe.getDataBaseType())) {
                throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
            }
 
            return connection;
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取链接失败", e);
            log.error(url);
            throw new BaseException(ErrorCode.GET_CONNECTION_FAIL);
        }
    }
 
    /**
     * 验证连接有效性
     *
     * @param connection
     * @param DriverTypeEnum
     * @return
     */
    public static boolean connectionValidity(Connection connection, DataBaseType DriverTypeEnum) {
        try {
            String validationQuery = DriverTypeEnum.getValidationQuery();
            try (PreparedStatement pst = connection.prepareStatement(validationQuery)) {
                boolean execute = pst.execute();
                return execute;
            }
        } catch (Exception e) {
            log.error("验证连接有效性失败", e);
            return false;
        }
 
    }
 
 
}