赞
踩
声明:本博客所有文章都是原创,不会有任何抄袭现象。请转载的朋友,标注出处,谢谢。
最近比较流行springboot微服务,那么持久层到底怎么样才算好?面对高并发的压力,如何抵制?本文将以JDBC来讲解敏捷开发,抵制高并发。本文为正在使用springboot的朋友提供帮助。对于零经验的朋友们,建议先学习下springboot的相关知识,然后再看这篇文章。
说到JDBC,我们第一件事是什么?先导入jar包对不对。JDK啥的一些基础包我就不多说了,下图是mysql的驱动包。
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
下面要说的是代码应该如何写,怎么写?如何优,怎么优的问题。大部分初学者,都会写个static的Connection然后再释放连接。殊不知开关连接是最消耗资源的,就像创建线程一样。那我们有没有什么办法让连接从始至终只实例一次呢?答案肯定是有的。先附上dbcp的maven包
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-dbcp2</artifactId>
- </dependency>
- public class JdbcUtils {
-
- private static final ThreadLocal<Connection> CONNECTION_HOLDER;
-
- private static final BasicDataSource DATA_SOURCE = new BasicDataSource();
-
- private JdbcUtils() {
- }
-
- static {
- CONNECTION_HOLDER = new ThreadLocal<Connection>();
- Properties conf = loadProps("dbconfig.properties");
- String driverClass = conf.getProperty("jdbc.driverClass");
- String url = conf.getProperty("jdbc.url");
- String username = conf.getProperty("jdbc.username");
- String password = conf.getProperty("jdbc.password");
- DATA_SOURCE.setDriverClassName(driverClass);
- DATA_SOURCE.setUrl(url);
- DATA_SOURCE.setUsername(username);
- DATA_SOURCE.setPassword(password);
-
-
- }
注意:提到两个东西,ThreadLocal和BasicDataSource。Threadlocal看上去像是本地线程的意思,我认为更好的词汇应该是本地变量。它会给每个访问的线程一个自己的实例,不存在线程阻塞的状况,我认为它也可以叫异步处理,因为我喜欢使用它进行异步编程。BasicDataSource翻译就是基本的数据源,没错,它就是连接池。
其实你可以把他们看作是线程池和连接池,用来管理数据的操作,这就是上面提到的,是实例一次的解决办法。我把连接的配置写在properties的文件里,然后和大家一样用流读取配置,把配置信息交给连接池来管理。有人似乎看到一行代码是这样写的:
- try(){
- }catch(Exception e){}
初学者甚至前辈也会问,try后面可以加括号?你耍我呢吧?答案是确实可以,这是JDK7的功能,但并不是什么都可以往里写,它的功能是自己帮你关闭连接,哪些连接呢?我们看下源码
。没错,只能关闭那些实现了Closeable接口的类。那么你还用不用手动关闭了?当然不用了。朋友说,你快别扯犊子了,赶紧说吧。说说怎么用吧,太墨迹了。
- private static Connection getConnection() {
- Connection conn = CONNECTION_HOLDER.get();
- if (conn == null) {
- try {
- conn = DATA_SOURCE.getConnection();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- CONNECTION_HOLDER.set(conn);
- }
- }
- return conn;
- }
-
- //资源的释放
- private static void release(Connection conn, PreparedStatement st,ResultSet rs) {
- if (rs != null) {
- try {
- rs.close();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- } finally {
- rs = null;
- }
- }
- if (st != null) {
- try {
- st.close();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- } finally {
- st = null;
- }
- }
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- } finally {
- conn = null;
- }
- }
- }
注意:释放连接,并没有真正的关闭,只是把连接放回连接池里而已。
附上一个公用的查询方法,返回List里面包的Map集合。
- /**
- * @author PQF
- * @category 根据SQL进行查询返回一个List实体集合
- * @param 1.传送一个查询的sql语句
- * @param 2.sql中使用占位符(?)所对应的实际值
- * @param 3.你要查询的列
- * @throws Exception
- */
- public static List<Map<String, String>> queryEntityList(String sql,
- List<String> list, String[] column) throws Exception {
- List<Map<String, String>> entityList = new ArrayList<>();
- if (sql.isEmpty() || column.length < 1) {
- throw new Exception("SQL语句不能为空,并且列的长度不能小于1");
- }
- Connection conn = getConnection();
- PreparedStatement prepareStatement = null;
- ResultSet result = null;
- try {
- prepareStatement = conn.prepareStatement(sql.toString());
- if(BaseUtil.ObjectNotNull(list)){
- for (int i = 1; i <= list.size(); i++) {
- prepareStatement.setString(i, list.get(i-1));
- }
- }
- result = prepareStatement.executeQuery();
- Map<String, String> mapList = null;
- while (result.next()) {
- mapList = new HashMap<>();
- for (Object col : column) {
- mapList.put((String) col, result.getString((String) col));
- }
- entityList.add(mapList);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- release(conn, prepareStatement, result);
- }
- return entityList;
- }
- public static boolean ObjectNotNull(Object object){
- return object != null && !"".equals(object) && !object.equals("null") ? true : false;
- }
至此,就可以了。亲测50并发毫无压力,2000并发只需1秒多搞定。是不是很给力,觉得还行就点个赞吧,让更多的人一起分享。
这是我写的第4篇文章,愿我微不足道的力量与您一同成长。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。