您当前的位置: 首页 > 

梁云亮

暂无认证

  • 2浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JDBC工具类

梁云亮 发布时间:2019-09-29 10:23:54 ,浏览量:2

版本一:最基本的Jdbc工具类
public class JdbcUtil {
    private static String url = "jdbc:mysql://localhost:3306/db_data_show_5?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false";
    private static String password = "root";
    private static String user = "root";

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 释放资源
     *
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void release(ResultSet rs, Statement stmt, Connection conn) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 获取连接
     *
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        final Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }
}
版本二:抽取连接信息后的工具类
  • 第一步:在resources目录下创建mysql.properties文件
url=jdbc:mysql://localhost:3306/db_data_show_5?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false
password=root
user=root
  • 第二步:使用配置文件的工具类
public class JdbcUtil {
    private static String url ;
    private static String password;
    private static String user;

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            final Properties properties = new Properties();
            //getResourceAsStream:读取文件,在JavaSE和javaWeb中都可以用,注意路径问题
            final InputStream is = JdbcUtil.class.getResourceAsStream("/mysql.properties");
            properties.load(is);
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            is.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接
     *
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        final Connection conn= DriverManager.getConnection(url, user, password);
        return conn;
    }
    /**
     * 释放资源
     *
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void release(ResultSet rs, Statement stmt, Connection conn) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws SQLException {
        final Connection conn = getConnection();
        System.out.println(conn);
    }
}
版本三:添加Druid数据库连接支持
  • 添加Druid依赖

    com.alibaba
    druid
    1.1.17

  • 修改mysql.properties
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_data_show_5?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false
username=root
password=root

# 初始化时创建的连接的个数
initialSize=10
# 处于活跃状态的连接的个数
maxActive=20
# 连接最多等待时长
maxWait=6000
  • 修改JdbcUtil:
public class JdbcUtil {
    private static DataSource dataSource;

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            final Properties properties = new Properties();
            //getResourceAsStream:读取文件,在JavaSE和javaWeb中都可以用,注意路径问题
            final InputStream is = JdbcUtil.class.getResourceAsStream("/mysql.properties");
            properties.load(is);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
           is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接
     *
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        final Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }
    /**
     * 释放资源
     *
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void release(ResultSet rs, Statement stmt, Connection conn) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws SQLException {
        final Connection conn = getConnection();
        System.out.println(conn);
    }
}

上面代码在单线程中使用是没有任何问题的,但是如果在多线程中使用呢?很显然,在多线程中使用会存在线程安全问题:第一,上面方法有进行同步,很可能在getConnection方法中会多次创建connection;第二,由于connection是共享变量,那么必然在调用connection的地方需要使用到同步来保障线程安全,因为很可能一个线程在使用connection进行数据库操作,而另外一个线程调用release关闭链接。

所以出于线程安全的考虑,必须将这段代码的两个方法进行同步处理,并且在调用connection的地方需要进行同步处理。这样将会大大影响程序执行效率,因为一个线程在使用connection进行数据库操作的时候,其他线程只有等待。

仔细分析一下这个问题,这地方到底需不需要将connection变量进行共享?事实上,是不需要的。假如每个线程中都有一个connection变量,各个线程之间对connection变量的访问实际上是没有依赖关系的,即一个线程不需要关心其他线程是否对这个connection进行了修改的。到这里,可能会有朋友想到,既然不需要在线程之间共享这个变量,可以直接这样处理,在每个需要使用数据库连接的方法中具体使用时才创建数据库链接,然后在方法调用完毕再释放这个连接。比如下面这样:

public class BookDaoImpl implements BookDao {
    @Override
    public int insert(Book book) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public int update(Book book) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public int deleteById(Integer id) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public List selectAll() throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public List selectWithPage(Integer pageNum, Integer pageSize) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public List selectByName(String name) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
    @Override
    public Book selectById(Integer id) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        ......
    }
}

由于每次都是在方法内部创建的连接,那么线程之间自然不存在线程安全问题。但是这样会有一个致命的影响:导致服务器压力非常大,并且严重影响程序执行性能。由于在方法中需要频繁地开启和关闭数据库连接,这样不尽严重影响程序执行效率,还可能导致服务器压力巨大。

这种情况下使用ThreadLocal是再适合不过的了,因为ThreadLocal在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。

但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

版本四:添加LocalThread以支持并发
public class JdbcUtil {
    private static DataSource dataSource;
    private static ThreadLocal threadLocal = new ThreadLocal();

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            final Properties properties = new Properties();

            //getResourceAsStream:读取文件,在JavaSE和javaWeb中都可以用,注意路径问题
            final InputStream is = JdbcUtil.class.getResourceAsStream("/mysql.properties");
            properties.load(is);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
            is.close();
        } catch (Exception e) {
            throw new RuntimeException("读取配置文件错误");
        }

    }
    /**
     * 获取连接
     *
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() {
       Connection conn = threadLocal.get();
        try {
            if (conn == null || conn.isClosed()) {
                conn = dataSource.getConnection();
                threadLocal.set(conn);
            }
        } catch (SQLException e) {
            throw new RuntimeException("获取连接失败!");
        }
        return conn;
    }
    /**
     * 释放资源
     *
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void release(ResultSet rs, Statement stmt, Connection conn) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                        threadLocal.remove(); 
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws SQLException {
        final Connection conn = getConnection();
        System.out.println(conn);
    }
}
关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.0513s