e42cc8631e46c003ca04691dc6b966bb91903c65.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. package org.jeecg.common.util.dynamic.db;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.commons.lang3.ArrayUtils;
  5. import org.jeecg.common.exception.JeecgBootException;
  6. import org.jeecg.common.exception.JeecgBootException;
  7. import org.jeecg.common.system.vo.DynamicDataSourceModel;
  8. import org.jeecg.common.util.ReflectHelper;
  9. import org.jeecg.common.util.oConvertUtils;
  10. import org.springframework.jdbc.core.JdbcTemplate;
  11. import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
  12. import javax.sql.DataSource;
  13. import java.sql.SQLException;
  14. import java.util.HashMap;
  15. import java.util.List;
  16. import java.util.Map;
  17. /**
  18. * Spring JDBC 实时数据库访问
  19. *
  20. * @author chenguobin
  21. * @version 1.0
  22. * @date 2014-09-05
  23. */
  24. @Slf4j
  25. public class DynamicDBUtil {
  26. /**
  27. * 获取数据源【最底层方法,不要随便调用】
  28. *
  29. * @param dbSource
  30. * @return
  31. */
  32. private static DruidDataSource getJdbcDataSource(final DynamicDataSourceModel dbSource) {
  33. DruidDataSource dataSource = new DruidDataSource();
  34. String driverClassName = dbSource.getDbDriver();
  35. String url = dbSource.getDbUrl();
  36. String dbUser = dbSource.getDbUsername();
  37. String dbPassword = dbSource.getDbPassword();
  38. dataSource.setDriverClassName(driverClassName);
  39. dataSource.setUrl(url);
  40. //dataSource.setValidationQuery("SELECT 1 FROM DUAL");
  41. dataSource.setTestWhileIdle(true);
  42. dataSource.setTestOnBorrow(false);
  43. dataSource.setTestOnReturn(false);
  44. dataSource.setBreakAfterAcquireFailure(true);
  45. dataSource.setConnectionErrorRetryAttempts(0);
  46. dataSource.setUsername(dbUser);
  47. dataSource.setMaxWait(30000);
  48. dataSource.setPassword(dbPassword);
  49. log.info("******************************************");
  50. log.info("* *");
  51. log.info("*====【"+dbSource.getCode()+"】=====Druid连接池已启用 ====*");
  52. log.info("* *");
  53. log.info("******************************************");
  54. return dataSource;
  55. }
  56. /**
  57. * 通过 dbKey ,获取数据源
  58. *
  59. * @param dbKey
  60. * @return
  61. */
  62. public static DruidDataSource getDbSourceByDbKey(final String dbKey) {
  63. //获取多数据源配置
  64. DynamicDataSourceModel dbSource = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
  65. //先判断缓存中是否存在数据库链接
  66. DruidDataSource cacheDbSource = DataSourceCachePool.getCacheBasicDataSource(dbKey);
  67. if (cacheDbSource != null && !cacheDbSource.isClosed()) {
  68. log.debug("--------getDbSourceBydbKey------------------从缓存中获取DB连接-------------------");
  69. return cacheDbSource;
  70. } else {
  71. DruidDataSource dataSource = getJdbcDataSource(dbSource);
  72. if(dataSource!=null && dataSource.isEnable()){
  73. DataSourceCachePool.putCacheBasicDataSource(dbKey, dataSource);
  74. }else{
  75. throw new JeecgBootException("动态数据源连接失败,dbKey:"+dbKey);
  76. }
  77. log.info("--------getDbSourceBydbKey------------------创建DB数据库连接-------------------");
  78. return dataSource;
  79. }
  80. }
  81. /**
  82. * 关闭数据库连接池
  83. *
  84. * @param dbKey
  85. * @return
  86. */
  87. public static void closeDbKey(final String dbKey) {
  88. DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
  89. try {
  90. if (dataSource != null && !dataSource.isClosed()) {
  91. dataSource.getConnection().commit();
  92. dataSource.getConnection().close();
  93. dataSource.close();
  94. }
  95. } catch (SQLException e) {
  96. e.printStackTrace();
  97. }
  98. }
  99. private static JdbcTemplate getJdbcTemplate(String dbKey) {
  100. DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
  101. return new JdbcTemplate(dataSource);
  102. }
  103. /**
  104. * Executes the SQL statement in this <code>PreparedStatement</code> object,
  105. * which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
  106. * <code>DELETE</code>; or an SQL statement that returns nothing,
  107. * such as a DDL statement.
  108. */
  109. public static int update(final String dbKey, String sql, Object... param) {
  110. int effectCount;
  111. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  112. if (ArrayUtils.isEmpty(param)) {
  113. effectCount = jdbcTemplate.update(sql);
  114. } else {
  115. effectCount = jdbcTemplate.update(sql, param);
  116. }
  117. return effectCount;
  118. }
  119. /**
  120. * 支持miniDao语法操作的Update
  121. *
  122. * @param dbKey 数据源标识
  123. * @param sql 执行sql语句,sql支持minidao语法逻辑
  124. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  125. * @return
  126. */
  127. public static int updateByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  128. int effectCount;
  129. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  130. //根据模板获取sql
  131. sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  132. NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  133. effectCount = namedParameterJdbcTemplate.update(sql, data);
  134. return effectCount;
  135. }
  136. public static Object findOne(final String dbKey, String sql, Object... param) {
  137. List<Map<String, Object>> list;
  138. list = findList(dbKey, sql, param);
  139. if (oConvertUtils.listIsEmpty(list)) {
  140. log.error("Except one, but not find actually");
  141. return null;
  142. }
  143. if (list.size() > 1) {
  144. log.error("Except one, but more than one actually");
  145. }
  146. return list.get(0);
  147. }
  148. /**
  149. * 支持miniDao语法操作的查询 返回HashMap
  150. *
  151. * @param dbKey 数据源标识
  152. * @param sql 执行sql语句,sql支持minidao语法逻辑
  153. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  154. * @return
  155. */
  156. public static Object findOneByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  157. List<Map<String, Object>> list;
  158. list = findListByHash(dbKey, sql, data);
  159. if (oConvertUtils.listIsEmpty(list)) {
  160. log.error("Except one, but not find actually");
  161. }
  162. if (list.size() > 1) {
  163. log.error("Except one, but more than one actually");
  164. }
  165. return list.get(0);
  166. }
  167. /**
  168. * 直接sql查询 根据clazz返回单个实例
  169. *
  170. * @param dbKey 数据源标识
  171. * @param sql 执行sql语句
  172. * @param clazz 返回实例的Class
  173. * @param param
  174. * @return
  175. */
  176. @SuppressWarnings("unchecked")
  177. public static <T> Object findOne(final String dbKey, String sql, Class<T> clazz, Object... param) {
  178. Map<String, Object> map = (Map<String, Object>) findOne(dbKey, sql, param);
  179. return ReflectHelper.setAll(clazz, map);
  180. }
  181. /**
  182. * 支持miniDao语法操作的查询 返回单个实例
  183. *
  184. * @param dbKey 数据源标识
  185. * @param sql 执行sql语句,sql支持minidao语法逻辑
  186. * @param clazz 返回实例的Class
  187. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  188. * @return
  189. */
  190. @SuppressWarnings("unchecked")
  191. public static <T> Object findOneByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  192. Map<String, Object> map = (Map<String, Object>) findOneByHash(dbKey, sql, data);
  193. return ReflectHelper.setAll(clazz, map);
  194. }
  195. public static List<Map<String, Object>> findList(final String dbKey, String sql, Object... param) {
  196. List<Map<String, Object>> list;
  197. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  198. if (ArrayUtils.isEmpty(param)) {
  199. list = jdbcTemplate.queryForList(sql);
  200. } else {
  201. list = jdbcTemplate.queryForList(sql, param);
  202. }
  203. return list;
  204. }
  205. /**
  206. * 支持miniDao语法操作的查询
  207. *
  208. * @param dbKey 数据源标识
  209. * @param sql 执行sql语句,sql支持minidao语法逻辑
  210. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  211. * @return
  212. */
  213. public static List<Map<String, Object>> findListByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  214. List<Map<String, Object>> list;
  215. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  216. //根据模板获取sql
  217. sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  218. NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  219. list = namedParameterJdbcTemplate.queryForList(sql, data);
  220. return list;
  221. }
  222. //此方法只能返回单列,不能返回实体类
  223. public static <T> List<T> findList(final String dbKey, String sql, Class<T> clazz, Object... param) {
  224. List<T> list;
  225. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  226. if (ArrayUtils.isEmpty(param)) {
  227. list = jdbcTemplate.queryForList(sql, clazz);
  228. } else {
  229. list = jdbcTemplate.queryForList(sql, clazz, param);
  230. }
  231. return list;
  232. }
  233. /**
  234. * 支持miniDao语法操作的查询 返回单列数据list
  235. *
  236. * @param dbKey 数据源标识
  237. * @param sql 执行sql语句,sql支持minidao语法逻辑
  238. * @param clazz 类型Long、String等
  239. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  240. * @return
  241. */
  242. public static <T> List<T> findListByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  243. List<T> list;
  244. JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  245. //根据模板获取sql
  246. sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  247. NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  248. list = namedParameterJdbcTemplate.queryForList(sql, data, clazz);
  249. return list;
  250. }
  251. /**
  252. * 直接sql查询 返回实体类列表
  253. *
  254. * @param dbKey 数据源标识
  255. * @param sql 执行sql语句,sql支持 minidao 语法逻辑
  256. * @param clazz 返回实体类列表的class
  257. * @param param sql拼接注入中需要的数据
  258. * @return
  259. */
  260. public static <T> List<T> findListEntities(final String dbKey, String sql, Class<T> clazz, Object... param) {
  261. List<Map<String, Object>> queryList = findList(dbKey, sql, param);
  262. return ReflectHelper.transList2Entrys(queryList, clazz);
  263. }
  264. /**
  265. * 支持miniDao语法操作的查询 返回实体类列表
  266. *
  267. * @param dbKey 数据源标识
  268. * @param sql 执行sql语句,sql支持minidao语法逻辑
  269. * @param clazz 返回实体类列表的class
  270. * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  271. * @return
  272. */
  273. public static <T> List<T> findListEntitiesByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  274. List<Map<String, Object>> queryList = findListByHash(dbKey, sql, data);
  275. return ReflectHelper.transList2Entrys(queryList, clazz);
  276. }
  277. }