数据库JDBC操作和数据库连接池

数据库操作

1. JDBC

1.1 根据driver、url、username、password信息建立连接然后进行数据库操作;

主要步骤:
//1.加载驱动
Class.forname();
//2. 获取链接
Connection connnection = DriverManager.getConnection(url,username,password);
//3. 获取Statement对象
Statement statement = connection.createStatement();
//4. 定义SQL
String sql = "select * from users";
//5. 执行
ResultSet rs  = statement.executeQuery(sql);
//6. 获取结果
String id,username,passowrd;
List<User> users = new ArrayList<User>();
while(rs.next())
{
    id = rs.getInt("id");
	username = rs.getString("username");
	password = rs.getString("password");
	//TODO:
	
	User user = new User();
	user.setID(id,username,password);
	users.add(user);
}
//7. 回收资源 rs,statement,connection,安装资源创建顺序的逆序;
try...catch... finally 
在finally内回收资源,防止前面抛异常,资源无法回收。
if(rs!=null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if(stmt!=null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if(conn!=null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }

1.2 待优化点

(1) JDBC参数可配

InputStream in = ResourceLoader.class.getClassLoader().getResourceAsStream();
ps = new Properties();
ps.load(in);
value = ps.getProperty(property);

(2) 结果集封装
定义对象类RowRapper

(3) Statement优化
a.statement重复编译SQL语句,当语句相同时,效率较低;
b.当用户传递参数时,如果添加一个语句如“or 1=1”,会将数据全部查询出来。存在安全性问题(SQL注入攻击);
因此引入PreparedStatemet对象,对sql进行预编译;

           
String sql = "insert into users(id,name,email) values(null,?,?)";
preStmt = connection.prepareStatement(sql);
preStmt.setObject(1,"李三");
preStmt.setObject(2,"123456");
 
 //返回影响的条数
int i = preStmt.executeUpdate();

2. 数据库连接池

2.1 为什么需要连接池

每操作一次数据库,都需要创建一次链接和释放一次链接,比较浪费资源。(创建、断开connection会消耗一定的时间和IO资源。)
在这里插入图片描述
图来自于网络,侵删;

2.2 如何实现连接池

在初始化时,创建一定数量的数据库连接放在连接池。当连接不够时,会再重新创建连接池;

    DataSource 接口,提供了获取数据库链接的方法
    
    Connection getConnection() throws SQLException;
    Connection getConnection(String username, String password)
    throws SQLException;

2.3 常用的数据库连接池

2.3.1 DBCP
2.3.2 C3P0
实现DataSource接口
类的层次
public interface PooledDataSource extends DataSource {

public abstract class AbstractComboPooledDataSource extends AbstractPoolBackedDataSource implements PooledDataSource,

public final class ComboPooledDataSource extends AbstractComboPooledDataSource

获取链接
 ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setDriverClass(driver);
        cpds.setJdbcUrl(url);
        cpds.setUser(usernmae);
        cpds.setPassword(password);

        cpds.getConnection();

进一步优化:读取配置文件获取链接;
(1)默认配置
(2)指定配置

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
<!--		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>-->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/c3p0_db?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf-8</property>
		<property name="user">root</property>
		<property name="password">000</property>
	</default-config>
	<named-config name="my_ds">
		<!--		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>-->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/c3p0_db?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf-8</property>
		<property name="user">root</property>
		<property name="password">000</property>
	</named-config>
</c3p0-config>

获取链接的方式:

ComboPooledDataSource ds = new ComboPooledDataSource();
Connnection connection = ds.getConnection(); //默认的配置
Connnection connection = ds.getConnection("my_ds"); //指定的配置

2.3 常用的DB工具:DBUtils

主要接口:


public interface ResultSetHandler<T> {
    T handle(ResultSet var1) throws SQLException;
}

public class QueryRunner extends AbstractQueryRunner {
    public QueryRunner() {
    }
    public QueryRunner(DataSource ds) {
        super(ds);
    }
    public <T> T query(Connection conn, String sql, Object param, ResultSetHandler<T> rsh) throws SQLException {
        return this.query(conn, false, sql, rsh, param);
    }
    public <T> T query(String sql, Object param, ResultSetHandler<T> rsh) throws SQLException {
        Connection conn = this.prepareConnection();
        return this.query(conn, true, sql, rsh, param);
    }
    public int update(Connection conn, String sql) throws SQLException {
        return this.update(conn, false, sql, (Object[])null);
    }
      public int update(String sql) throws SQLException {
        Connection conn = this.prepareConnection();
        return this.update(conn, true, sql, (Object[])null);
    }

    public int update(String sql, Object param) throws SQLException {
        Connection conn = this.prepareConnection();
        return this.update(conn, true, sql, param);
    }
     public <T> T insert(String sql, ResultSetHandler<T> rsh) throws SQLException {
        return this.insert(this.prepareConnection(), true, sql, rsh, (Object[])null);
    }

    public <T> T insert(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
        return this.insert(this.prepareConnection(), true, sql, rsh, params);
    }

    public <T> T insert(Connection conn, String sql, ResultSetHandler<T> rsh) throws SQLException {
        return this.insert(conn, false, sql, rsh, (Object[])null);
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值