前面我们演示了一个简单的数据库连接池,我们再结合之前的mysql数据库操作类MysqlHandler修改一下,实现一个使用连接池的mysql操作类。
首先,我们先得有一个自定义的异常类,猫哥主要想用它演示下抛出特定异常。
package sql;//Java中的类可以用不同的package(包)划分,这样更加条理
public class MysqlException extends Exception{//自定义异常类,因为继承了Exception类,所以成为了异常家族的一员
public MysqlException(String msg){//构造函数,包含一条消息,此处我们简单的以消息内容区分不同的数据库异常
super(msg);
}
}
注意本篇中所有的类都是在package sql下的,也就是在包sql下。如果把类比做文件,那包就是文件夹——整理类的作用,如此而已。
OK,然后我们稍微改造下我们的数据库连接池类如下:
package sql;
import java.sql.*;//这个java.sql和上面自定义的sql是一回事。名字都不一样嘛,一个叫java.sql一个叫sql。就像李老四和李四是两个人名。
import java.util.LinkedList;
public class MysqlPool {
//使用static保证全局共享一个池子,使用LinkedList是因为经常删除、添加元素
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//最大连接数
private static int maxCount=20;
static{//此处修改为使用静态代码块实现数据库连接池初始化,注意静态代码块中的语句只会执行一次,且在类初始化时候执行
//下面的代码无需捕获异常,因为准备在MysqlHandler中捕获数据库异常
for(int i=0;i<maxCount;i++){
MysqlHandler handler=new MysqlHandler();//此处借用MysqlHandler获取数据库连接,为啥借用?因为MysqlHandler干这些事比较方便
//建立连接,并放于池中,不用担心这个连接找不到了,因为已经是池中之物了
//此处应该注意,因为connection是要放入池中的,所以此处buildConnection建立的connection不用再依赖MysqlHandler类管理connection的释放问题
Connection connection = handler.buildConnection();
pool.add(connection);//所有连接都非常保险的在pool中放置,随时可以取用
}
}
public static Connection getConnecton() throws MysqlException{//此处将异常抛出,在外面处理。也可以选择在getConnecton内部处理,看程序员决策了
if(pool.size()==0)//分配完了
{
throw new MysqlException("数据库连接池资源短缺,无连接可分配");
}
else{
return pool.remove(0);//删除第一个对象并返回
}
}
public static void release(Connection connection){//使用完的归还给池子
pool.add(connection);
}
}
需要注意两点:1是静态代码块的使用,让整个程序不用再管理数据库连接池的初始化问题,相对于手工init()初始化所有连接,静态代码块在MysqlPool类第一次加载时自动调用显得更加的牛X。2是注意我们使用MysqlHandler 的buildConnection方法拿到连接,这个方法没有什么变化,也没有变化的必要,就是建立一个数据库连接。
OK,再来看我们封装的操作类:
package sql;
import java.sql.*;//导入数据库相关类库
/**
* MysqlHandler MySQL数据库管理类,使用数据库连接池
* @author 猫哥
* @date 2016.1.9
*/
public class MysqlHandler{
//依然是那熟悉的三个必备参数
private Connection conn = null;
private Statement stmt = null;
private ResultSet rs = null;
//建立数据库连接,此处仅用于提供原始连接,供放入池中使用
public Connection buildConnection() {
String driver = "com.mysql.jdbc.Driver";//MySQL数据库的驱动程序名
String url = "jdbc:mysql://localhost:3306/java?useUnicode=true&characterEncoding=utf-8";//数据库连接字符串
String user = "root";//用户名
String password = "Pass1234";//密码
try{
Class.forName(driver);//加载驱动程序
conn=DriverManager.getConnection(url,user,password);//输入必备参数,获取连接
}
catch(Exception ex){
ex.printStackTrace();//可以输出比较详细的异常信息
}
return conn;
}
//操作1,“增删改查”中,增、删、改都是执行sql语句,无需返回ResultSet结果集,所以设置为一个方法
public int execute(String sql){
try {
conn=MysqlPool.getConnecton();//用时从池中取,很爽快
stmt=conn.createStatement();
int affectedCount = stmt.executeUpdate(sql);//此处真正执行stmt定义的操作
return affectedCount;//这个是收到影响的行数
}
catch(MysqlException myEx){//可以针对自定义的异常单独处理
myEx.printStackTrace();
return -2;//返回-2,表示数据库连接池分配超限,可以在外面针对性处理,其实可以直接抛到更外层处理,还是看程序员决策了
}
catch (Exception ex) {
ex.printStackTrace();
return -1;//返回-1,表示执行失败了,有异常
}
}
//操作2,如果是查询,需返回结果集
public ResultSet query(String sql)throws Exception{
try{
conn=MysqlPool.getConnecton();//用时从池中取,很爽快
stmt=conn.createStatement();
rs = stmt.executeQuery(sql);//执行pstmt中定义的查询
return rs;//将结果集返回
}
catch(MysqlException myEx){//可以针对自定义的异常单独处理
throw new MysqlException(myEx.getMessage());//还可以往外抛,可以针对查询时数据库连接池连接不足问题单独处理(例如延迟响应用户请求以下)
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
//操作3,释放资源
public void sayGoodbye(){
//此处注意,conn在池中管理,此处无需关闭
if(rs!=null){//关闭结果集,这个不关闭也浪费
try {
rs.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
if(stmt!=null){//关闭Statement,不要浪费
try {
stmt.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
MysqlPool.release(conn);
}
}
OK,最后,单独写一个测试类,测试以下:
package sql;
import java.sql.*;
public class SqlTest {
public static void main(String[] args) throws Exception {//此处我们不处理异常
// TODO Auto-generated method stub
MysqlHandler hand=new MysqlHandler();
ResultSet rs=null;//可以使用多次
//查
rs=hand.query("select * from student_info");
//展示结果
System.out.println("\n查询结果如下:");
while(rs.next()){
System.out.print(rs.getInt(1) + "|");
System.out.print(rs.getString(2) + "\t");
}
//增加2个
int addCount=hand.execute("insert into student_info (student_name) values('火星人'),('水星人')");
System.out.println("\n增加了"+addCount+"个");
//删除一个
int delCount=hand.execute("delete from student_info where student_name='张三'");
System.out.println("\n删除了"+delCount+"个");
//修改一个,把李四改造成火星人
int changeCount=hand.execute("update student_info set student_name='火星人李四' where student_name='李四'");
System.out.println("\n修改了"+changeCount+"个");
//查
rs=hand.query("select * from student_info");
System.out.println("\n查询结果如下:");
while(rs.next()){
System.out.print(rs.getInt(1) + "|");
System.out.print(rs.getString(2) + "\t");
}
hand.sayGoodbye();
}
}
OVER。
点击查看更多内容
2人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦