Alibaba Druid数据库连接池直接起飞

1、什么是数据库连接池

为什么要使用连接池:我们使用Java开发时,就需要访问数据库,而Java不能直接访问数据库,中间得通过JDBC来建立程序和数据库的连接,执行一个事务就需要创建一个连接,而程序和数据库建立连接的过程是最耗时间的,当程序变得庞大,如果频繁的让程序和数据库建立连接,则耗时非常大,所以,程序员们就有了连接池的概念

连接池:存放着与数据库连接的通道,也就是JDBC中的Connection,事先定义好n 个连接,在程序启动的时候就初始化这些连接,后期直接从连接池中拿就行了,最后放回到连接池中,中间就省略了大量的重复连接和释放的操作。

2、Druid连接池

Druid:德鲁D连接池是由Alibaba团队开发,其中引入了“缓加载“概念。

缓加载:在创建连接池对象的时候,不会对事先定义好的连接通道个数与数据库建立连接,而是在中连接池中拿第一个连接通道的时候,连接池就检查内部是否有用的连接通道,如果有就给出,如果没有就执行事先定义好的n个连接通道与数据库建立连接。

3、Druid连接池的jar/依赖

一、下载Druid.jar

Druid.1.2.8.jar

二、导入依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druidartifactId>
    <version>1.2.8version>
dependency>

两种方式任选其一。

4、代码体现

4.1、创建一个properties文件

创建一个properties文件,主要用来给Druid连接池一个约束
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/javaweb?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username = root
password = 123456
initialSize = 5 //初始化连接通道个数
maxActive = 5 //最大的可用连接通道个数
maxWait = 3000 //当所有的连接通道都被占用后,需要等待的最大时间,单位为毫秒

4.2、创建一个DruidUtils类

将配置文件读入到内存中等待被拿取连接通道

public class DruidUtils {

    private static DataSource dataSource = null;
    private static Properties properties = null;

    static{
        properties = new Properties();
        try {
            //将配置文件加载进入内存,采用反射技术
            properties.load(DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //通过工厂设计模式得到一个连接池对象,得到的是一个连接池对象,而不是连接对象哦
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException("连接池配置文件加载失败");
        }
    }
    //将连接池对象开放给外部使用
    public static DataSource getDataSource(){
        return dataSource;
    }
    //从连接池对象中获取Connection
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

4.3、测试

1、 需要先得到一个连接池对象,然后从连接池对象中得到连接
2、得到连接后的操作和JDBC操作数据库是一样的

4.3.0、打印、查看连接池
private static DataSource dataSource = DruidUtils.getDataSource(); //得到连接池对象

public static void main(String[] args){
	System.out.println(dataSource); 
}

结果
Alibaba Druid数据库连接池直接起飞_第1张图片
解析
Alibaba Druid数据库连接池直接起飞_第2张图片

4.3.1、添加用户方法
    private static String addUser(User user){
        String sql = "INSERT INTO user VALUES(?,?,?,?,?)";//SQL语句
        int result = 0; //执行后的结果
        try {
        //从连接池对象中得到连接通道
            Connection connection = dataSource.getConnection();
		//下面的操作都和JDBC中的一样,执行SQL语句
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,user.getId());
            preparedStatement.setString(2,user.getUserName());
            preparedStatement.setString(3,user.getPassword());
            preparedStatement.setString(4,user.getSex());
            preparedStatement.setString(5,user.getPhone());
            result = preparedStatement.executeUpdate();
            //操作完成后一定要将连接再次放到连接池中,不然连接池就一直处于被占用的状态,不能给其他的事物使用。
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return result > 0 ? "添加用户成功" : "添加用户失败";
    }
4.3.1、得到所有用户信息
    private static List<User> getUserList() {
        List<User> userList = new ArrayList<>();
        ResultSet result = null;
        String sql = "SELECT * FROM user";
        try {
        	//从连接池中得到连接通道
            Connection connection = dataSource.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            result = preparedStatement.executeQuery();
            User user = null;
            while (result.next()) {
                user = new User(result.getString("id"),result.getString("username"),
                        result.getString("password"), result.getString("sex"), result.getString("phone"));
                userList.add(user);
            }
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return userList;
    }
4.3.3、Main方法
public class DruidPoolTest {
    private static DataSource dataSource = null;

    public static void main(String[] args) {
        dataSource = DruidUtils.getDataSource(); //得到连接池对象

        System.out.println("-----------向数据库中添加一个用户-----------------");
        User user = new User("6","王水煮","999999","女","13888887878");
        System.out.println(addUser(user));

     	System.out.println("--------------查询所有-------------");
        List<User> userList = getUserList();
        for(User user : userList){
            System.out.println(user.toString());
        }
    }
}
结果

目前数据库内一共有五条用户信息
Alibaba Druid数据库连接池直接起飞_第3张图片
执行完Main方法中的操作后
Alibaba Druid数据库连接池直接起飞_第4张图片
一共有六条数据,数据添加成功。由于Druid连接池采用的“缓加载”技术,在程序执行到第一次得到连接通道的时候,由于连接池内没有连接,就需要初始化N条连接通道,所以会一开始比较慢。

5、没有将连接还给连接池引发的异常

我事先在properties文件中定义的连接通道条数是五条,最大活动条数也是五条。
而现在我要获取六条:

    public static void main(String[] args) {
        dataSource = DruidUtils.getDataSource(); //得到连接池对象
        try {
            Connection connection1 = dataSource.getConnection();//第一个连接
            Connection connection2 = dataSource.getConnection();//第二个连接
            Connection connection3 = dataSource.getConnection();//第三个连接
            Connection connection4 = dataSource.getConnection();//第四个连接
            Connection connection5 = dataSource.getConnection();//第五个连接
            Connection connection6 = dataSource.getConnection();//第六个连接
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

直接报错
Alibaba Druid数据库连接池直接起飞_第5张图片
原因

原因一:连接池中没有可用的连接通道了,定义了五条通道,最大可用的也是五条通道,所有就没有可用的了。
原因二 :我执行完一个事务后没有将连接释放,导致其他事务无法得到连接通道。

解决办法

解决办法一:扩大连接池中最大可用的连接条数
initialSize = 5 //初始化五条连接通道
maxActive = 10 //最大可用的连接通道为 10条

解决办法二 : 事务执行完后,将连接还给连接池。

个人建议还是使用解决办法二,因为在大型的项目中,不建议去动不动就加大连接通道的条数

6、总结

Druid连接池也是现在比较流行的一个连接池技术,但是它只能解决连接通道在连接和释放的性能优化。其他操作数据库的方式还是和JDBC一样,所以目前市场上也出现了MyBatis等框架技术。

你可能感兴趣的:(java技术,java,数据库,jdbc,连接池,jar)