【在Maven项目中,手动连接和使用连接池(dbcp\c3p0)连接数据库的流程】

一、在Maven项目中,原生态手动–连接数据库并实行CRUD的流程

1.在pom.xml中导入数据库驱动的依赖包

<!--数据库驱动依赖(匹配与自己安装的MySQL版本)-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.24</version>
</dependency>

2.在resources目录下,创建db.properties配置类文件并编写

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/school?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

3.在com.GQ.Xxx包下,创建并编写工具类JdbcUtils

public class JdbcUtils {

    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    //1.属性资源导入
    static {
        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); //获取输入流

            Properties properties = new Properties();  //创建空属性列表
            properties.load(in);  //加载流资源

            //获取属性资源
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //2.驱动只用加载一次
            Class.forName(driver);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //3.获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //4.释放连接资源
    public static void release(Connection connection, Statement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

4.在com.GQ.Yyy包下,编写测试类JdbcTest01(使用Statement类型对象,会存在Sql注入问题)

public class JdbcTest01 {
    public static void main(String[] args) {
        //getUserById("'张三'"); //正常情况
        getUserById("'' or 1=1"); //非正常情况,出现sql注入问题
    }

    //CRUD业务代码
    public static void getUserByName(String name){
        //5.提升作用域:为了能在finally中使用
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JdbcUtils.getConnection();  //1.获取数据库的连接
            statement = connection.createStatement(); //2.获取SQL的执行对象(使用Statement类型对象,存在Sql注入问题)

            //核心:sql语句
            String sql = "SELECT * FROM student WHERE studentname = " + name ;

            //3.获取结果(集)
            resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
                System.out.println(resultSet.getString("studentno"));
                System.out.println(resultSet.getString("loginpwd"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //4.释放资源
            JdbcUtils.release(connection, statement, resultSet);
        }
    }
}

4.1使用PreparedStatement类型对象,防止Sql注入问题,同时提高效率

public class JdbcTest02 {
    public static void main(String[] args) {
        getUserById("张三"); //正常情况
        //getUserById("'' or 1=1"); //没有返回值,预防sql注入问题
        //prepareStatement防止sql注入的本质:把传递进来的参数当作字符,若其中存在转义字符,就会直接忽略(如'会被直接转义)
    }

    //CRUD业务代码
    public static void getUserByName(String name){
        //5.提升作用域:为了能在finally中使用
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JdbcUtils.getConnection();

            //使用?占位符,来代替参数
            String sql = "SELECT * FROM student WHERE studentname = ?";
            statement = connection.prepareStatement(sql); //1.使用prepareStatement来预编译sql(先写sql但先不执行)

            //2.手动给参数赋值
            statement.setString(1,name);   //index默认从1开始

            //3.执行
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getString("studentno"));
                System.out.println(resultSet.getString("loginpwd"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //4.释放资源
            JdbcUtils.release(connection, statement, resultSet);
        }
    }
}

二、在Maven项目中,通过数据库连接池–连接数据库并实行CRUD的流程

  1. 数据库连接池的基本思想

    • 为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
  2. 为什么需要数据库连接池?

    1. 资源重用:由于数据库连接得以重用,避免了频繁创建和释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
    2. 更快的系统反应速度:数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
    3. 新的资源分配手段:对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。
    4. 统一的连接管理,避免数据库连接泄漏:在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
  3. 多种开源的数据库连接池

    • JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现:

      1. DBCP:是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。
      2. C3P0:是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用。
      3. Druid:是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,速度快,又稳定,但是速度不确定是否有BoneCP快
    • DataSource 通常被称为数据源,它包含连接池连接池管理两个部分,习惯上也经常把 DataSource 称为连接池

    • DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。

    • 特别注意:

      • 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
      • 当数据库访问结束后,程序还是像以前一样关闭数据库连接:connnection.close(); 但connnection.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池

4.DBCP的使用:

1.在pom.xml中导入dbcp数据库连接池的依赖包

<!--前提:先导入数据库驱动依赖-->
<!--dbcp数据库连接池-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.9.0</version>
</dependency>

2.在resources目录下,创建dbcp-config.properties配置类文件并编写

#连接设置(driverClassName是DBCP数据源中定义好的固定名字)
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc)NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

3.在com.GQ.Xxx包下,创建并编写工具类JdbcUtils_DBCP

public class JdbcUtils_DBCP {
    //4.提升作用域
    private static BasicDataSource dataSource = null;

    //1.获取数据源 dataSource
    static {
        try {
            InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcp-config.properties"); //获取输入流
            Properties properties = new Properties();  //创建空属性列表
            properties.load(in);  //加载流资源

            //创建数据源 工厂模式--->创建对象
            //在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现,而DBCP连接池就是java.sql.DataSource接口的一个具体实现
            dataSource = BasicDataSourceFactory.createDataSource(properties);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //2.获取连接 (数据源dataSource自带连接)
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    //3.释放连接资源
    public static void release(Connection connection, Statement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

4.在com.GQ.Yyy包下,编写测试类JdbcTestDBCP

public class JdbcTestDBCP {
    public static void main(String[] args) {
        getUserByName("张伟"); 
    }

    //CRUD业务代码
    public static void getUserByName(String name){
        //5.提升作用域:为了能在finally中使用
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JdbcUtils_DBCP.getConnection(); //利用数据源改变的地方一

            //使用?占位符,来代替参数
            String sql = "SELECT * FROM student WHERE studentname = ?";
            statement = connection.prepareStatement(sql); //1.使用prepareStatement来预编译sql(先写sql但先不执行)

            //2.手动给参数赋值
            statement.setString(1,name);   //index默认从1开始

            //3.执行
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getString("studentno"));
                System.out.println(resultSet.getString("loginpwd"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //4.释放资源
            JdbcUtils_DBCP.release(connection, statement, resultSet); //利用数据源改变的地方二
        }
    }
}

5.C3P0的使用:

1.在pom.xml中导入C3P0数据库连接池的依赖包

<!--前提:先导入数据库驱动依赖-->
<!--c3p0数据库连接池-->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>mchange-commons-java</artifactId>
    <version>0.2.20</version>
</dependency>

2.在resources目录下,创建c3p0-config.xml配置类文件并编写

<c3p0-config>
    <!--C3P0的缺省(默认)配置,
        如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源-->
    <default-config>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/school?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

    <!--C3P0的命名配置,
        如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源-->
    <named-config name="MySQL">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/school?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>

</c3p0-config>

3.在com.GQ.Xxx包下,创建并编写工具类JdbcUtils_C3P0

public class JdbcUtils_C3P0 {
    //4.提升作用域
    private static ComboPooledDataSource dataSource = null;

    //1.获取数据源 dataSource
    static {
        try {
            //创建数据源 (直接new一个ComboPooledDataSource()对象就可以获得数据源)
            dataSource = new ComboPooledDataSource();           //C3P0的缺省(默认)配置
            //ComboPooledDataSource dataSource = new ComboPooledDataSource("MySQL");  //C3P0的命名配置(配置文件写法)

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //2.获取连接 (数据源dataSource自带连接)
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    //3.释放连接资源
    public static void release(Connection connection, Statement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

4.在com.GQ.Yyy包下,编写测试类JdbcTestC3P0

public class JdbcTestC3P0 {
    public static void main(String[] args) {
        getUserByName("张三"); //正常情况
    }

    //CRUD业务代码
    public static void getUserByName(String name){
        //5.提升作用域:为了能在finally中使用
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JdbcUtils_C3P0.getConnection();//利用数据源改变的地方一

            //使用?占位符,来代替参数
            String sql = "SELECT * FROM student WHERE studentname = ?";
            statement = connection.prepareStatement(sql); //1.使用prepareStatement来预编译sql(先写sql但先不执行)

            //2.手动给参数赋值
            statement.setString(1,name);   //index默认从1开始

            //3.执行
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getString("studentno"));
                System.out.println(resultSet.getString("loginpwd"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //4.释放资源
            JdbcUtils_C3P0.release(connection, statement, resultSet); //利用数据源改变的地方二
        }
    }
}
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C3P0是一个流行的Java数据库连接池管理器,它可以帮助你有效地管理和复用数据库连接,避免频繁创建和关闭连接所带来的性能开销。当你使用C3P0与MySQL数据库集成时,你需要进行以下几个步骤: 1. **添加依赖**:在你的项目,首先需要将C3P0库作为Maven或Gradle的依赖添加到构建文件。 ```xml <!-- Maven --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> <!-- 选择合适的版本 --> </dependency> // Gradle implementation 'com.mchange:c3p0:0.9.5.2' ``` 2. **配置初始化**:在应用启动时,需要初始化C3P0连接池。通常会在Spring Boot应用使用`DataSource`接口的配置。 ```java @Configuration public class DataSourceConfig { @Value("${jdbc.url}") private String url; @Value("${jdbc.user}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource() { c3p0.ComboPooledDataSource dataSource = new c3p0.ComboPooledDataSource(); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); dataSource.setMaxPoolSize(10); // 设置最大连接数 dataSource.setMinPoolSize(5); // 设置最小连接数 dataSource.setMaxIdleTime(300); // 设置最长空闲时间 return dataSource; } } ``` 3. **注入使用**:在需要使用数据库的地方,你可以通过`@Autowired`注入`DataSource`来获取连接。 ```java @Service public class MyService { @Autowired private DataSource dataSource; public void performTask() { try (Connection connection = dataSource.getConnection()) { // 这里进行数据库操作 } catch (SQLException e) { e.printStackTrace(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值