赞
踩
为什么要使用连接池:我们使用Java开发时,就需要访问数据库,而Java不能直接访问数据库,中间得通过JDBC来建立程序和数据库的连接,执行一个事务就需要创建一个连接,而程序和数据库建立连接的过程是最耗时间的,当程序变得庞大,如果频繁的让程序和数据库建立连接,则耗时非常大,所以,程序员们就有了连接池的概念
连接池:存放着与数据库连接的通道,也就是JDBC中的Connection,事先定义好n 个连接,在程序启动的时候就初始化这些连接,后期直接从连接池中拿就行了,最后放回到连接池中,中间就省略了大量的重复连接和释放的操作。
Druid:德鲁D连接池是由Alibaba团队开发,其中引入了“缓加载“概念。
缓加载:在创建连接池对象的时候,不会对事先定义好的连接通道个数与数据库建立连接,而是在中连接池中拿第一个连接通道的时候,连接池就检查内部是否有用的连接通道,如果有就给出,如果没有就执行事先定义好的n个连接通道与数据库建立连接。
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
两种方式任选其一。
创建一个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 //当所有的连接通道都被占用后,需要等待的最大时间,单位为毫秒
将配置文件读入到内存中等待被拿取连接通道
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(); } }
1、 需要先得到一个连接池对象,然后从连接池对象中得到连接
2、得到连接后的操作和JDBC操作数据库是一样的
private static DataSource dataSource = DruidUtils.getDataSource(); //得到连接池对象
public static void main(String[] args){
System.out.println(dataSource);
}
结果
解析
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 ? "添加用户成功" : "添加用户失败"; }
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; }
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()); } } }
目前数据库内一共有五条用户信息
执行完Main方法中的操作后
一共有六条数据,数据添加成功。由于Druid连接池采用的“缓加载”技术,在程序执行到第一次得到连接通道的时候,由于连接池内没有连接,就需要初始化N条连接通道,所以会一开始比较慢。
我事先在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();
}
}
直接报错
原因
原因一:连接池中没有可用的连接通道了,定义了五条通道,最大可用的也是五条通道,所有就没有可用的了。
原因二 :我执行完一个事务后没有将连接释放,导致其他事务无法得到连接通道。
解决办法
解决办法一:扩大连接池中最大可用的连接条数
initialSize = 5 //初始化五条连接通道
maxActive = 10 //最大可用的连接通道为 10条
解决办法二 : 事务执行完后,将连接还给连接池。
个人建议还是使用解决办法二,因为在大型的项目中,不建议去动不动就加大连接通道的条数
Druid连接池也是现在比较流行的一个连接池技术,但是它只能解决连接通道在连接和释放的性能优化。其他操作数据库的方式还是和JDBC一样,所以目前市场上也出现了MyBatis等框架技术。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。