一个关于数据库操作的优化实例

本专栏将从基础开始,循序渐进,讲解数据库的基本概念以及使用,希望大家都能够从中有所收获,也请大家多多支持。
专栏地址: 数据库必知必会
相关软件地址:软件地址
如果文章知识点有错误的地方,请指正!大家一起学习,一起进步。

1 一个关于数据库操作的优化实例

1.1 原始版本

添加依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
    </dependencies>

创建数据库与表:

create database learnDesignPattern;

use  learnDesignPattern;

create table t_student(
    id int(32) primary key auto_increment,
    name varchar(50),
    age varchar(50)
);

alter table t_student change column age  age int(32);

创建学生类Student.java:

public class Student {
    
    
    private int age;
    private String name;
    private int id;

    public Student(int age, String name) {
    
    
        this.age = age;
        this.name = name;
    }

    public Student(int age, String name, int id) {
    
    
        this.age = age;
        this.name = name;
        this.id = id;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
}

创建对学术的增删查改StudentDao.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class StudentDao {
    
    

    //添加学生信息
    public void add(Student stu){
    
    
        String sql = "insert into t_student(name,age) values(?,?)";
        Connection conn = null;
        Statement st = null;

        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/learnDesignPattern?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT","root","root");
            //3.创建语句对象
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            //4.执行sql
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            //释放资源
            try{
    
    
                if (st != null){
    
    
                    st.close();
                }

                if(conn!=null){
    
    
                    conn.close();
                }
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
        }
    }

    //删除学生信息
    public void delete(int id){
    
    
        String sql = "delete from t_student where id=?";
        Connection conn = null;
        Statement st = null;

        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/learnDesignPattern?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT","root","root");
            //3.创建语句对象
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,id);
            //4.执行sql
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            //释放资源
            try{
    
    
                if (st != null){
    
    
                    st.close();
                }

                if(conn!=null){
    
    
                    conn.close();
                }
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
        }
    }

    //修改学生信息
    public void update(Student stu){
    
    
        String sql = "update t_student set name =?,age=? where id=?";
        Connection conn = null;
        Statement st = null;

        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/learnDesignPattern?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT","root","root");
            //3.创建语句对象
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            ps.setObject(3,stu.getId());
            //4.执行sql
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            //释放资源
            try{
    
    
                if (st != null){
    
    
                    st.close();
                }

                if(conn!=null){
    
    
                    conn.close();
                }
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
        }
    }
}

1.2 使用JDBCUtil封装代码

可以看到上面代码功能没有问题,但是重复代码太多,因此可以进行抽取,把重复代码放到一个工具类JDBCUtil里。

  • JDBCUtil.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JDBCUtil {
    
    
    private JDBCUtil(){
    
    }

    static {
    
    
        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
    
    
        try{
    
    
            //2.获取数据库连接
            return DriverManager.getConnection("jdbc:mysql://localhost:3306/learnDesignPattern?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT","root","root");
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        return null;
    }

    public static void close(ResultSet rs, Statement st, Connection conn){
    
    
        //释放资源
        try{
    
    
            if(rs != null){
    
    
                rs.close();
            }

            if (st != null){
    
    
                st.close();
            }

            if(conn!=null){
    
    
                conn.close();
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }


}
  • StudentDao.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class StudentDao {
    
    

    //添加学生信息
    public void add(Student stu){
    
    
        String sql = "insert into t_student(name,age) values(?,?)";
        Connection conn = null;
        Statement st = null;
        PreparedStatement ps = null;
        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(null,ps,conn);
        }
    }

    //删除学生信息
    public void delete(int id){
    
    
        String sql = "delete from t_student where id=?";
        Connection conn = null;
        Statement st = null;
        PreparedStatement ps = null;
        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setObject(1,id);
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(null,ps,conn);
        }
    }

    //修改学生信息
    public void update(Student stu){
    
    
        String sql = "update t_student set name =?,age=? where id=?";
        Connection conn = null;
        Statement st = null;
        PreparedStatement ps = null;
        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            ps.setObject(1,stu.getId());
            ps.executeUpdate();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(null,ps,conn);
        }
    }
}

1.3 使用配置文件,以及查询和修改统一方式

3.2的方法任然有部分冗余,可以把查询和修改的方法进行统一。

  • JDBCUtil.java
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
    
    

    private static Properties p = null;

    private JDBCUtil(){
    
    }

    static {
    
    
        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = loader.getResourceAsStream("db.properties");
            p = new Properties();
            p.load(inputStream);
            Class.forName(p.getProperty("driverClassName"));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
    
    
        try{
    
    
            //2.获取数据库连接
            return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        return null;
    }

    public static void close(ResultSet rs, Statement st, Connection conn){
    
    
        //释放资源
        try{
    
    
            if(rs != null){
    
    
                rs.close();
            }

            if (st != null){
    
    
                st.close();
            }

            if(conn!=null){
    
    
                conn.close();
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }


}
  • JDBCTemplate.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class JDBCTemplate {
    
    

    public static void update(String sql,Object... params){
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            ps.executeUpdate();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,conn);
        }

    }

    public static List<Student> query(String sql,Object... params){
    
    
        List<Student> list = new ArrayList<Student>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            rs = ps.executeQuery();
            while(rs.next()){
    
    
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu = new Student(id,name,age);
                list.add(stu);
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,conn);
        }

        return list;
    }
}
  • StudentDao.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class StudentDao {
    
    

    private Logger logger = LoggerFactory.getLogger(StudentDao.class);


    //添加学生信息
    public void add(Student stu){
    
    
        String sql = "insert into t_student(name,age) values(?,?)";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge()};
        JDBCTemplate.update(sql,params);
    }

    //删除学生信息
    public void delete(int id){
    
    
        String sql = "delete from t_student where id=?";
        JDBCTemplate.update(sql,id);
    }

    //修改学生信息
    public void update(Student stu){
    
    
        String sql = "update t_student set name =?,age=? where id=?";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge(),stu.getId()};
        JDBCTemplate.update(sql,params);
    }

    //查询
    public Student get(int id){
    
    
        String sql = "select * from t_student where id=?";
        List<Student> list = JDBCTemplate.query(sql, id);
        return list.size()>0?list.get(0):null;
    }

    //查询
    public List<Student> list(){
    
    
        String sql = "select * from t_student";
        return JDBCTemplate.query(sql);
    }
}

1.4 使用泛型处理多种返回结果

如果不仅要查询学生信息(List类型),还要查询学生数量,这时就要通过泛型来完成。

  • IRowMapper.java
import java.sql.ResultSet;
import java.util.List;

public interface IRowMapper<T> {
    
    
    T mapping(ResultSet rs) throws Exception;
}
  • StudentRowMapper.java
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class StudentRowMapper implements IRowMapper<List<Student>> {
    
    
    public List<Student> mapping(ResultSet rs) throws Exception {
    
    
        List<Student> list = new ArrayList<Student>();
        while(rs.next()){
    
    
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            Student stu = new Student(id,name,age);
            list.add(stu);
        }
        return list;
    }
}
  • JDBCUtil
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
    
    

    private static Properties p = null;

    private JDBCUtil(){
    
    }

    static {
    
    
        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = loader.getResourceAsStream("db.properties");
            p = new Properties();
            p.load(inputStream);
            Class.forName(p.getProperty("driverClassName"));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
    
    
        try{
    
    
            //2.获取数据库连接
            return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        return null;
    }

    public static void close(ResultSet rs, Statement st, Connection conn){
    
    
        //释放资源
        try{
    
    
            if(rs != null){
    
    
                rs.close();
            }

            if (st != null){
    
    
                st.close();
            }

            if(conn!=null){
    
    
                conn.close();
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }


}
  • StudentDao
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.transform.Result;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class StudentDao {
    
    

    private Logger logger = LoggerFactory.getLogger(StudentDao.class);


    //添加学生信息
    public void add(Student stu){
    
    
        String sql = "insert into t_student(name,age) values(?,?)";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge()};
        JDBCTemplate.update(sql,params);
    }

    //删除学生信息
    public void delete(int id){
    
    
        String sql = "delete from t_student where id=?";
        JDBCTemplate.update(sql,id);
    }

    //修改学生信息
    public void update(Student stu){
    
    
        String sql = "update t_student set name =?,age=? where id=?";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge(),stu.getId()};
        JDBCTemplate.update(sql,params);
    }

    //查询
    public Student get(int id){
    
    
        String sql = "select * from t_student where id=?";
        List<Student> list = JDBCTemplate.query(sql, new StudentRowMapper(),id);
        return list.size()>0?list.get(0):null;
    }

    //查询
    public List<Student> list(){
    
    
        String sql = "select * from t_student";
        return JDBCTemplate.query(sql,new StudentRowMapper());
    }

    public int getCount(){
    
    
         String sql = "select count(*) total from t_student";
         int totalCount = (int)JDBCTemplate.query(sql, new IRowMapper<Integer>() {
    
    
             public Integer mapping(ResultSet rs) throws Exception{
    
    
                Integer totalCount = null;
                if(rs.next()){
    
    
                    totalCount = rs.getInt("total");
                }
                return totalCount;
             }
         });

         return totalCount;
    }
}
  • JDBCTemplate.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class JDBCTemplate {
    
    

    public static void update(String sql,Object... params){
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            ps.executeUpdate();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,conn);
        }

    }

    public static <T> T query(String sql,IRowMapper<T> rsh,Object... params){
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try{
    
    
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            rs = ps.executeQuery();
            return rsh.mapping(rs);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,conn);
        }

        return null;
    }
}

1.5 连接池

以上代码每次执行sql都要获取数据库连接,这就导致资源的浪费,所以可以使用数据库连接池来优化代码。

  • Pool.java
package JDBC.Pool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public abstract class Pool {
    
    
//    private Logger logger = LoggerFactory.getLogger(Pool.class);

    public String propertiesName = "db.properties";
    private static Pool instance = null;

    //最大连接数
    protected int maxConnection = 100;

    //保持连接数
    protected int stayConnection = 10;

    //驱动字符串
    protected String driverName = null;

    //驱动类
    protected Driver driver = null;

    protected Pool(){
    
    
        try{
    
    
            init();
            loadDrivers(driverName);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * @Author cgw
     * @Description 初始化所有从配置文件中读取的成员变量
     * @return: void
     * @Date  2022/2/18 16:13
     **/
    private void init() throws IOException{
    
    
        Properties properties = new Properties();
        InputStream is = Pool.class.getClassLoader().getResourceAsStream(propertiesName);
        try {
    
    
            properties.load(is);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        this.driverName = properties.getProperty("driverClassName");

        if(properties.getProperty("maxConnection")!=null){
    
    
            this.maxConnection = Integer.parseInt(properties.getProperty("maxConnection"));
        }

        if(properties.getProperty("stayConnection")!=null){
    
    
            this.stayConnection = Integer.parseInt(properties.getProperty("stayConnection"));
        }
    }

    /**
     * @Author cgw
     * @Description 装载和注册所有JDBC驱动程序
     * @param driverName: 接收驱动字符串
     * @return: void
     * @Date  2022/2/18 16:12
     **/
    private void loadDrivers(String driverName){
    
    
        String driverClassName= driverName;
        try {
    
    
            driver = (Driver) Class.forName(driverClassName).newInstance();
            DriverManager.registerDriver(driver);
//            logger.info("成功注册JDBC驱动程序:{}",driverClassName);
        } catch (Exception e) {
    
    
//            logger.info("无法注册JDBC驱动程序:{},异常:{}",driverClassName,e);
        }
    }
    
    /**
     * @Author cgw
     * @Description 获得一个可用的连接,如果没有,则创建一个连接,并且小于最大连接限制
     * @return: java.sql.Connection
     * @Date  2022/2/18 16:01
     **/
    public abstract Connection getConnection();

    /**
     * @Author cgw
     * @Description 获得一个连接,有时间限制
     * @param time: 设置该连接的持续时间(以毫秒为单位)
     * @return: java.sql.Connection
     * @Date  2022/2/18 16:02
     **/
    public abstract Connection getConnection(long time);

    /**
     * @Author cgw
     * @Description 将连接对象返回连接池
     * @param connection: 获得连接对象
     * @return: void
     * @Date  2022/2/18 16:03
     **/
    public abstract void freeConnection(Connection connection);

    /**
     * @Author cgw
     * @Description 返回当前空闲的连接数
     * @return: int
     * @Date  2022/2/18 16:04
     **/
    public abstract int getNumFree();

    /**
     * @Author cgw
     * @Description 返回当前工作的连接数
     * @return: int
     * @Date  2022/2/18 16:04
     **/
    public abstract int getNumActive();

    /**
     * @Author cgw
     * @Description 关闭所有连接,撤销驱动注册,此方法为单例方法
     * @return: void
     * @Date  2022/2/18 16:14
     **/
    protected synchronized void release(){
    
    
        try{
    
    
            DriverManager.deregisterDriver(driver);
//            logger.info("撤销JDBC驱动程序:{}",driver.getClass().getName());
        } catch (SQLException e) {
    
    
//            logger.info("无法撤销JDBC驱动程序:{},异常:{}",driver.getClass().getName(),e);
        }

    }
}
  • DBConnectionPool.java
package JDBC.Pool;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

//final修饰的类不能被继承
public final class DBConnectionPool extends Pool {
    
    
//    private Logger logger = LoggerFactory.getLogger(DBConnectionPool.class);
    private Vector<Connection> freeConnections = new Vector<Connection>();//存放产生的连接对象容器

    private String url = null;//连接字符串
    private String username = null;//用户名
    private String password = null;//密码

    private int numTotal;//连接总数
    private static int numFree = 0;//空闲的连接数, 放入到连接池里的连接数量
    private static int numActive = 0;//在活跃的连接数,默认为0,指的是在使用的线程数量

    private static DBConnectionPool dbConnectionPool = null;//连接池实例对象

    private DBConnectionPool(){
    
    
        try{
    
    
            init();
            for(int i=0;i<stayConnection;i++){
    
    
                Connection c = newConnection();
                if(null != c){
    
    
                    freeConnections.addElement(c);
                    numTotal++;
                    numFree++;
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }

    // 使用单例模式获取连接池
    public static DBConnectionPool getInstance() {
    
    
        if (dbConnectionPool == null){
    
    
            synchronized (Pool.class){
    
    
                if(dbConnectionPool == null){
    
    
                    dbConnectionPool = new DBConnectionPool();
                }
            }
        }
        return dbConnectionPool;
    }

    /**
     * @Author cgw
     * @Description 初始化
     * @return: void
     * @Date  2022/2/18 16:22
     **/
    private void init() throws Exception{
    
    
        InputStream is = DBConnectionPool.class.getClassLoader().getResourceAsStream(propertiesName);
        Properties properties = new Properties();
        properties.load(is);
        this.driverName = properties.getProperty("driverClassName");
        this.url = properties.getProperty("url");
        this.username = properties.getProperty("username");
        this.password = properties.getProperty("password");
    }

    /**
     * @Author cgw
     * @Description 创建一个新连接
     * @return: java.sql.Connection
     * @Date  2022/2/18 16:26
     **/
    private Connection newConnection(){
    
    
        Connection connection = null;
        try{
    
    
            if(username == null || password == null){
    
    
                connection = DriverManager.getConnection(url);
            }else {
    
    
                connection = DriverManager.getConnection(url,username,password);
            }
//            logger.info("连接池创建一个新的连接");
        } catch (Exception e) {
    
    
//            logger.info("无法创建url:{}的连接,错误原因:{}",url,e);
            return null;
        }
        return connection;
    }

    /**
     * @Author cgw
     * @Description 获取一个可用连接
     * @return: java.sql.Connection
     * @Date  2022/2/18 19:14
     **/
    public synchronized  Connection getConnection() {
    
    
        Connection connection = null;
        if(freeConnections.size() > 0){
    
    
            connection = (Connection)freeConnections.firstElement();
            numFree--;
            freeConnections.removeElementAt(0);
            try{
    
    
                if(connection.isClosed()){
    
    
//                    logger.info("从连接池删除一个无效连接");
                    numTotal--;
                    connection = getConnection();
                }
            } catch (Exception e) {
    
    
//                logger.info("从连接池删除一个无效连接");
            }
            //没有空闲连接且当前连接小于允许最大值,若最大值为0,则不限制
        }else if(maxConnection == 0 || numTotal < maxConnection){
    
    
            connection = newConnection();
            numTotal++;
        }

        if(connection != null){
    
    
            numActive++;
        }

        return connection;
    }

    //获取一个可用连接,并加上等待时间限制,时间为毫秒
    public Connection getConnection(long timeout) {
    
    
        long startTime = new Date().getTime();
        Connection connection = null;
        while((connection = getConnection()) == null){
    
    
            try{
    
    
                //20毫秒执行一次
                Thread.sleep(20);
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }

            if((new Date().getTime() - startTime) >= timeout){
    
    
                return null;//如果超时,则返回
            }
        }
        return connection;
    }

    public void freeConnection(Connection con) {
    
    
        freeConnections.addElement(con);
        numFree++;
        numActive--;
//        notifyAll();//解锁
    }

    public int getNumFree() {
    
    
        return numFree;
    }

    public int getNumActive() {
    
    
        return numActive;
    }

    //释放所有连接
    public synchronized void release() {
    
    
        try {
    
    
            Enumeration allConnections = freeConnections.elements();
            while (allConnections.hasMoreElements()) {
    
    
                Connection conn = (Connection) allConnections.nextElement();
                try {
    
    
                    conn.close();
                    numFree--;
                } catch (Exception e) {
    
    
                    System.out.println("无法关闭连接池中的连接");
                }
            }
            freeConnections.removeAllElements();
            numTotal=0;
        } catch (Exception e) {
    
    
            System.out.println("释放失败!");
        } finally {
    
    
            //卸载驱动
            super.release();
        }

    }
}
  • JDBCUtil.java
package JDBC.Util;

import JDBC.Pool.DBConnectionPool;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
    
    

    private static Properties p = null;

    private JDBCUtil(){
    
    }

    static {
    
    
        try{
    
    
            //1.初始化驱动类,在初始化的时候通过静态代码块中的java.sql.DriverManager.registerDriver(new Driver())注册驱动
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = loader.getResourceAsStream("db.properties");
            p = new Properties();
            p.load(inputStream);
            Class.forName(p.getProperty("driverClassName"));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
    
    
        try{
    
    
            //2.获取数据库连接
//            return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
            return DBConnectionPool.getInstance().getConnection();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        return null;
    }

    public static void close(ResultSet rs, Statement st, Connection connection){
    
    
        //释放资源
        try{
    
    
            if(rs != null){
    
    
                rs.close();
            }

            if (st != null){
    
    
                st.close();
            }

            if(connection!=null){
    
    
                DBConnectionPool.getInstance().freeConnection(connection);
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }


}
  • IRowMapper.java
package JDBC.Util;

import java.sql.ResultSet;
import java.util.List;

public interface IRowMapper<T> {
    
    
    T mapping(ResultSet rs) throws Exception;
}
  • JDBCTemplate.java
package JDBC.Util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCTemplate {
    
    

    public static void update(String sql,Object... params){
    
    
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
    
    
            connection = JDBCUtil.getConnection();
            ps = connection.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            ps.executeUpdate();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,connection);
        }

    }

    public static <T> T query(String sql,IRowMapper<T> rsh,Object... params){
    
    
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try{
    
    
            connection = JDBCUtil.getConnection();
            ps = connection.prepareStatement(sql);
            for(int i=0;i<params.length;i++){
    
    
                ps.setObject(i+1,params[i]);
            }
            rs = ps.executeQuery();
            return rsh.mapping(rs);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtil.close(rs,ps,connection);
        }

        return null;
    }
}
  • StudentDao.java
package dao;

import JDBC.Util.IRowMapper;
import JDBC.Util.JDBCTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pojo.Student;

import java.sql.*;
import java.util.List;

public class StudentDao {
    
    

//    private Logger logger = LoggerFactory.getLogger(StudentDao.class);


    //添加学生信息
    public void add(Student stu){
    
    
        String sql = "insert into t_student(name,age) values(?,?)";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge()};
        JDBCTemplate.update(sql,params);
    }

    //删除学生信息
    public void delete(int id){
    
    
        String sql = "delete from t_student where id=?";
        JDBCTemplate.update(sql,id);
    }

    //修改学生信息
    public void update(Student stu){
    
    
        String sql = "update t_student set name =?,age=? where id=?";
        Object[] params = new Object[]{
    
    stu.getName(),stu.getAge(),stu.getId()};
        JDBCTemplate.update(sql,params);
    }

    //查询
    public Student get(int id){
    
    
        String sql = "select * from t_student where id=?";
        List<Student> list = JDBCTemplate.query(sql, new StudentRowMapper(),id);
        return list.size()>0?list.get(0):null;
    }

    //查询
    public List<Student> list(){
    
    
        String sql = "select * from t_student";
        return JDBCTemplate.query(sql,new StudentRowMapper());
    }

    public int getCount(){
    
    
         String sql = "select count(*) total from t_student";
         int totalCount = (int)JDBCTemplate.query(sql, new IRowMapper<Integer>() {
    
    
             public Integer mapping(ResultSet rs) throws Exception{
    
    
                Integer totalCount = null;
                if(rs.next()){
    
    
                    totalCount = rs.getInt("total");
                }
                return totalCount;
             }
         });

         return totalCount;
    }
}
  • StudentRowMapper.java
package dao;

import JDBC.Util.IRowMapper;
import pojo.Student;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class StudentRowMapper implements IRowMapper<List<Student>> {
    
    
    public List<Student> mapping(ResultSet rs) throws Exception {
    
    
        List<Student> list = new ArrayList<Student>();
        while(rs.next()){
    
    
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            Student stu = new Student(id,name,age);
            list.add(stu);
        }
        return list;
    }
}
  • 测试代码
import dao.StudentDao;

public class ExectorThread extends Thread {
    
    

    @Override
    public void run() {
    
    
        StudentDao stuDao = new StudentDao();
        System.out.println("线程" + this.getName() + " " + stuDao.list());
    }
}

import dao.StudentDao;

public class TestApi {
    
    

    public static void main(String[] args) {
    
    
        for(int i = 0;i<200000;i++){
    
    
            Thread t = new Thread(new ExectorThread());
            t.setName(""+i);
            t.start();
        }
//        System.out.println("End");
//        StudentDao stuDao = new StudentDao();
//        stuDao.add(new Student(19,"bbb"));
//        System.out.println(stuDao.list());
//        System.out.println(stuDao.getCount());
//        System.out.println(stuDao.get(2).getName());
//        stuDao.add(new Student(18,"aaa"));
//        stuDao.update(new Student(19,"aaa",1));
//        stuDao.delete(1);
    }
}

猜你喜欢

转载自blog.csdn.net/Learning_xzj/article/details/125027447