当前位置:   article > 正文

springboot手写JDBC面对2000并发量毫无压力_springboot 手写jdbc

springboot 手写jdbc

声明:本博客所有文章都是原创,不会有任何抄袭现象。请转载的朋友,标注出处,谢谢。


最近比较流行springboot微服务,那么持久层到底怎么样才算好?面对高并发的压力,如何抵制?本文将以JDBC来讲解敏捷开发,抵制高并发。本文为正在使用springboot的朋友提供帮助。对于零经验的朋友们,建议先学习下springboot的相关知识,然后再看这篇文章。

说到JDBC,我们第一件事是什么?先导入jar包对不对。JDK啥的一些基础包我就不多说了,下图是mysql的驱动包。

  1. <dependency>
  2. <groupId>mysql</groupId>
  3. <artifactId>mysql-connector-java</artifactId>
  4. </dependency>

下面要说的是代码应该如何写,怎么写?如何优,怎么优的问题。大部分初学者,都会写个static的Connection然后再释放连接。殊不知开关连接是最消耗资源的,就像创建线程一样。那我们有没有什么办法让连接从始至终只实例一次呢?答案肯定是有的。先附上dbcp的maven包

  1. <dependency>
  2. <groupId>org.apache.commons</groupId>
  3. <artifactId>commons-dbcp2</artifactId>
  4. </dependency>


  1. public class JdbcUtils {
  2. private static final ThreadLocal<Connection> CONNECTION_HOLDER;
  3. private static final BasicDataSource DATA_SOURCE = new BasicDataSource();
  4. private JdbcUtils() {
  5. }
  6. static {
  7. CONNECTION_HOLDER = new ThreadLocal<Connection>();
  8. Properties conf = loadProps("dbconfig.properties");
  9. String driverClass = conf.getProperty("jdbc.driverClass");
  10. String url = conf.getProperty("jdbc.url");
  11. String username = conf.getProperty("jdbc.username");
  12. String password = conf.getProperty("jdbc.password");
  13. DATA_SOURCE.setDriverClassName(driverClass);
  14. DATA_SOURCE.setUrl(url);
  15. DATA_SOURCE.setUsername(username);
  16. DATA_SOURCE.setPassword(password);
  17. }

注意提到两个东西,ThreadLocal和BasicDataSource。Threadlocal看上去像是本地线程的意思,我认为更好的词汇应该是本地变量。它会给每个访问的线程一个自己的实例,不存在线程阻塞的状况,我认为它也可以叫异步处理,因为我喜欢使用它进行异步编程。BasicDataSource翻译就是基本的数据源,没错,它就是连接池。

其实你可以把他们看作是线程池和连接池,用来管理数据的操作,这就是上面提到的,是实例一次的解决办法。我把连接的配置写在properties的文件里,然后和大家一样用流读取配置,把配置信息交给连接池来管理。有人似乎看到一行代码是这样写的:

  1. try(){
  2. }catch(Exception e){}

初学者甚至前辈也会问,try后面可以加括号?你耍我呢吧?答案是确实可以,这是JDK7的功能,但并不是什么都可以往里写,它的功能是自己帮你关闭连接,哪些连接呢?我们看下源码

。没错,只能关闭那些实现了Closeable接口的类。那么你还用不用手动关闭了?当然不用了。朋友说,你快别扯犊子了,赶紧说吧。说说怎么用吧,太墨迹了。

  1. private static Connection getConnection() {
  2. Connection conn = CONNECTION_HOLDER.get();
  3. if (conn == null) {
  4. try {
  5. conn = DATA_SOURCE.getConnection();
  6. } catch (Exception e) {
  7. e.printStackTrace();
  8. } finally {
  9. CONNECTION_HOLDER.set(conn);
  10. }
  11. }
  12. return conn;
  13. }
  14. //资源的释放
  15. private static void release(Connection conn, PreparedStatement st,ResultSet rs) {
  16. if (rs != null) {
  17. try {
  18. rs.close();
  19. } catch (SQLException e) {
  20. throw new RuntimeException(e);
  21. } finally {
  22. rs = null;
  23. }
  24. }
  25. if (st != null) {
  26. try {
  27. st.close();
  28. } catch (SQLException e) {
  29. throw new RuntimeException(e);
  30. } finally {
  31. st = null;
  32. }
  33. }
  34. if (conn != null) {
  35. try {
  36. conn.close();
  37. } catch (SQLException e) {
  38. throw new RuntimeException(e);
  39. } finally {
  40. conn = null;
  41. }
  42. }
  43. }

注意释放连接,并没有真正的关闭,只是把连接放回连接池里而已。

附上一个公用的查询方法,返回List里面包的Map集合。

  1. /**
  2. * @author PQF
  3. * @category 根据SQL进行查询返回一个List实体集合
  4. * @param 1.传送一个查询的sql语句
  5. * @param 2.sql中使用占位符(?)所对应的实际值
  6. * @param 3.你要查询的列
  7. * @throws Exception
  8. */
  9. public static List<Map<String, String>> queryEntityList(String sql,
  10. List<String> list, String[] column) throws Exception {
  11. List<Map<String, String>> entityList = new ArrayList<>();
  12. if (sql.isEmpty() || column.length < 1) {
  13. throw new Exception("SQL语句不能为空,并且列的长度不能小于1");
  14. }
  15. Connection conn = getConnection();
  16. PreparedStatement prepareStatement = null;
  17. ResultSet result = null;
  18. try {
  19. prepareStatement = conn.prepareStatement(sql.toString());
  20. if(BaseUtil.ObjectNotNull(list)){
  21. for (int i = 1; i <= list.size(); i++) {
  22. prepareStatement.setString(i, list.get(i-1));
  23. }
  24. }
  25. result = prepareStatement.executeQuery();
  26. Map<String, String> mapList = null;
  27. while (result.next()) {
  28. mapList = new HashMap<>();
  29. for (Object col : column) {
  30. mapList.put((String) col, result.getString((String) col));
  31. }
  32. entityList.add(mapList);
  33. }
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. } finally {
  37. release(conn, prepareStatement, result);
  38. }
  39. return entityList;
  40. }

  1. public static boolean ObjectNotNull(Object object){
  2. return object != null && !"".equals(object) && !object.equals("null") ? true : false;
  3. }

至此,就可以了。亲测50并发毫无压力,2000并发只需1秒多搞定。是不是很给力,觉得还行就点个赞吧,让更多的人一起分享。

这是我写的第4篇文章,愿我微不足道的力量与您一同成长。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/271733
推荐阅读
相关标签
  

闽ICP备14008679号