【JavaWeb】2.封装jdbc工具类

本文探讨了两种不同的JDBC连接管理方式:一是使用ThreadLocal维护每个线程的数据库连接,以确保事务的正确性;二是引入阿里巴巴的Druid数据库连接池,通过配置初始化大小、最大活跃连接数等参数来优化数据库资源的使用。这两种方法都旨在提高应用的性能和并发能力。
  1. 初始版本
public final class JDBCUtil{
    //定义数据库连接相关参数
    private static String driver = "";
    private static String url = "";
    private static String user = "";
    private static String password = "";
    
    //私有化构造方法
    private JDBCUtil(){}
    
    //加载配置文件
    static {
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        driver = bundle.getString("driver");
        url = bundle.getString("url");
        user = bundle.getString("user");
        password = bundle.getString("password");
        
        //注册驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    //获取数据库连接
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    
    //关闭资源
    public static void closeAll(Connection con, Statement stmt, ResultSet rs){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace():
            }
        }
        
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 为了保证每个能够开启以及回滚事务,需要改进的JDBCUtil
public final class JDBCUtil {
    private static String driver = "";
    private static String url = "";
    private static String user = "";
    private static String password = "";
    
    //创建ThreadLocal类的对象,用于维护每个线程的数据库连接
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    //保证了每个线程只会有同一个Connection连接对象,如果使用单例的话,所有用户都必须要等待。
    
    //加载配置文件
    static {
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        driver = bundle.getString("driver");
        url = bundle.getString("url");
        user = bundle.getString("user");
        password = bundle.getString("password");
        
        //注册驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    //获取数据库连接
    public static Connection getConnection() {
        if (threadLocal.get() == null) {
            try {
                threadLocal.set(DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        return threadLocal.get();
    }
    
    //关闭资源
    public static void closeAll(Connection con, Statement stmt, ResultSet rs){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace():
            }
        }
        
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        if (con != null) {
            try {
                con.close();
                threadLocal.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 以上两种方式的配置文件
    jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jgs1904?useSSL=true&serverTimezone=GMT%2B8
user=root
password=root
  1. 使用alibaba的druid数据库连接池
public final class DataSourceUtil {

	private DataSourceUtil() {};
	
	private static Properties pro = new Properties();
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
	private static DataSource dataSource = null;
	
	static {
		// 1.将配置文件加载到properties集合内 
		InputStream is = Demo02.class.getClassLoader().getResourceAsStream("druid.properties");
		try {
			pro.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		// 2.使用properties集合内的配置参数初始化一个连接池
		try {
			dataSource = DruidDataSourceFactory.createDataSource(pro);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	// 获取数据库连接池
	public static DataSource getDataSource() {
		return dataSource;
	}
	
	// 获取数据库连接
	public static Connection getConnection() {
		if (threadLocal.get() == null) {
			try {
				threadLocal.set(dataSource.getConnection());
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return threadLocal.get();
	}
	
	// 关闭资源
	public static void closeAll(Connection con, Statement stmt, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		if (con != null) {
			try {
				con.close();
				// 销毁threadLocal中的连接对象
				threadLocal.remove();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

	}
}
  1. 配置文件 druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/jgs1904?useSSL=true&serverTimezone=GMT%2B8
username=root
password=root

#初始化时池中建立的连接数。
initialSize=2
#最大的可活跃的连接池数量
maxActive=300
#最大等待时间
maxWait=60000
#是否缓存preparedStatement
poolPreparedStatements=true
#池中能够缓冲的preparedStatement语句数量
maxPoolPreparedStatementPerConnectionSize=200
<think>我们正在处理一个关于JavaWeb项目中JDBC工具类封装的问题。根据用户需求,我们需要提供一个封装好的JDBC工具类示例。同时,我们还需要参考提供的引用内容,尤其是引用[3]和引用[4]中提到的工具类抽取和连接池的使用。 目标: 1.封装一个JDBC工具类,能够提供数据库连接,并关闭资源。 2.使用数据库连接池(如Druid)来管理连接,以提高性能。 3.考虑使用配置文件(如properties文件)来配置数据库连接参数。 步骤: 1.首先,我们需要一个配置文件(如druid.properties)来存放数据库连接信息。2.然后,我们创建一个工具类,使用静态代码块初始化连接池。 3.工具类中提供获取连接的方法,以及关闭资源的方法。参考引用[4]中Druid连接池的使用示例,以及引用[3]中工具类的结构。设计工具类:-类名:JDBCUtils-使用Druid连接池-静态数据源DataSource-静态代码块中加载配置文件并初始化连接池-提供静态方法getConnection()获取连接-提供静态方法close(Connection conn, Statementstmt, ResultSet rs)用于关闭资源,注意处理异常同时,参考引用[5]中关于DbUtils的描述,我们也可以考虑简单封装关闭操作。实现:1.配置文件druid.properties(放在src目录下,或者资源目录下):```driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8username=rootpassword=rootinitialSize=5maxActive=10maxWait=3000``` 2.工具类JDBCUtils.java: ```javaimport com.alibaba.druid.pool.DruidDataSourceFactory; importjavax.sql.DataSource; importjava.io.InputStream;import java.sql.Connection; importjava.sql.ResultSet;import java.sql.SQLException; importjava.sql.Statement; importjava.util.Properties; publicclass JDBCUtils{privatestatic DataSource dataSource;static{try {//加载配置文件Propertiesprop =new Properties();//使用类加载器获取资源流InputStream inputStream =JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");prop.load(inputStream);//创建连接池dataSource =DruidDataSourceFactory.createDataSource(prop);} catch(Exceptione){e.printStackTrace();throw newRuntimeException("初始化连接池失败");}}//获取数据库连接publicstatic ConnectiongetConnection() throwsSQLException{return dataSource.getConnection();}//关闭资源(重载多个方法,根据传入的资源不同进行关闭)publicstatic voidclose(Connection conn, Statementstmt, ResultSet rs) {if(rs!= null) {try{rs.close();} catch(SQLException e) {e.printStackTrace();}}if(stmt!= null) {try{stmt.close();}catch (SQLExceptione){e.printStackTrace();}}if (conn !=null){try {conn.close();//注意:连接池中的连接是归还给连接池,并不是真正关闭}catch (SQLExceptione){e.printStackTrace();}}}//重载关闭方法,用于关闭连接和语句public staticvoid close(Connectionconn,Statement stmt){close(conn,stmt, null);}//重载关闭方法,用于关闭连接publicstatic voidclose(Connection conn) {close(conn, null, null);} }``` 说明: 1.使用Druid连接池,通过静态代码块初始化连接池,只需要初始化一次。2.配置文件的加载使用类加载器从类路径(如src/main/resources)下加载。 3.提供了多个重载的close方法,方便调用。 4.注意:连接池中的连接调用close()方法时,并不会真正关闭连接,而是归还到连接池中。使用示例: 在DAO层中,我们可以这样使用:```javapublicclass UserDao {publicUserfindUserById(intid){Connection conn= null;PreparedStatementpstmt= null;ResultSetrs =null;Useruser =null;try{conn =JDBCUtils.getConnection();Stringsql ="SELECT* FROMuser WHEREid=?";pstmt= conn.prepareStatement(sql);pstmt.setInt(1,id);rs= pstmt.executeQuery();if(rs.next()){user =new User();user.setId(rs.getInt("id"));user.setUsername(rs.getString("username"));user.setPassword(rs.getString("password"));}}catch (SQLExceptione){e.printStackTrace();} finally{JDBCUtils.close(conn, pstmt,rs);}returnuser;}} ```注意事项:1.需要添加Druid的依赖(如果使用Maven,在pom.xml中添加):```xml<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version> <!--版本号根据实际情况选择--></dependency>``` 2.需要数据库驱动,如MySQL驱动:```xml<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.23</version></dependency>```这样,我们就封装了一个使用Druid连接池的JDBC工具类,可以有效地管理数据库连接,提高性能,并且使用方便。相关问题:1.除了Druid,还有哪些常见的数据库连接池?2.JDBC工具类中,如何处理事务? 3.如何防止SQL注入攻击?</think>### JavaWeb项目中JDBC封装工具类示例 在JavaWeb项目中,封装JDBC工具类可提高代码复用性、简化数据库操作并提升性能。以下是基于Druid连接池的完整工具类实现: #### 1. 配置文件:`druid.properties` ```properties # 数据库配置 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC username=root password=123456 # 连接池参数 initialSize=5 maxActive=20 maxWait=60000 minIdle=3 ``` #### 2. 工具类:`JDBCUtils.java` ```java import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.sql.*; import java.util.Properties; public class JDBCUtils { // 静态数据源 private static DataSource dataSource; // 静态代码块初始化连接池 static { try { Properties prop = new Properties(); // 加载配置文件(放在src/main/resources目录) prop.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties")); dataSource = DruidDataSourceFactory.createDataSource(prop); } catch (Exception e) { throw new RuntimeException("连接池初始化失败", e); } } // 获取数据库连接 public static Connection getConnection() { try { return dataSource.getConnection(); } catch (SQLException e) { throw new RuntimeException("获取连接失败", e); } } // 关闭资源(重载方法) public static void close(Connection conn, Statement stmt, ResultSet rs) { try { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); // 实际是归还给连接池 } catch (SQLException e) { e.printStackTrace(); } } public static void close(Connection conn, Statement stmt) { close(conn, stmt, null); } // 执行更新操作(增删改) public static int executeUpdate(String sql, Object... params) { try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { // 设置参数 for (int i = 0; i < params.length; i++) { pstmt.setObject(i + 1, params[i]); } return pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException("执行更新失败", e); } } } ``` #### 3. 使用示例 ```java // 查询用户 public User getUserById(int id) { String sql = "SELECT * FROM users WHERE id = ?"; try (Connection conn = JDBCUtils.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setInt(1, id); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { return new User( rs.getInt("id"), rs.getString("name"), rs.getString("email") ); } } } catch (SQLException e) { e.printStackTrace(); } return null; } // 更新用户 public int updateUser(User user) { String sql = "UPDATE users SET name=?, email=? WHERE id=?"; return JDBCUtils.executeUpdate(sql, user.getName(), user.getEmail(), user.getId() ); } ``` #### 关键设计说明: 1. **连接池管理**:使用Druid连接池替代传统DriverManager,显著提升性能[^4] 2. **资源自动关闭**:通过try-with-resources语法确保资源释放 3. **参数化查询**:使用`PreparedStatement`防止SQL注入攻击[^2] 4. **配置解耦**:数据库参数独立在配置文件中 5. **异常统一处理**:将SQLException转换为RuntimeException #### 依赖配置(Maven) ```xml <dependencies> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!-- Druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.16</version> </dependency> </dependencies> ``` > **注意事项**: > 1. 配置文件需放在`src/main/resources`目录 > 2. 事务管理需通过`Connection`的`setAutoCommit(false)`和`commit()/rollback()`实现[^2] > 3. 批量操作建议使用`addBatch()`和`executeBatch()`方法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JeffHan^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值