0%

JDBC邂逅——连接数据库与执行语句

使用 JDBC 可以方便的操作各种类型的数据库。以下记录一下 JDBC 的基础操作。

连接数据库

使用 DriverManager 建立 Connection

安装数据库服务和导入相应的 jar 包后,即可使用 JDBC 连接到数据库,得到一个 Connection 对象。

首先需要加载驱动程序,比如对于 mysql 数据库,可以使用如下代码加载驱动:

1
Class.forName("com.mysql.jdbc.Driver");

然后建立连接。常用的是 DriverManager.getConnection(String url,String user, String password) 方法。

其中,参数 url 指定数据库位置,格式为:

1
jdbc:subprotocol:subname

协议:子协议:数据源标识

比如,我们使用的是本地的 mysql,端口使用默认的 3306,需要连接的数据库名为 userinfo,那么 url 应该为

1
jdbc:mysql://localhost:3306/userinfo

同时,为了避免向数据库存入中文字符时出现乱码,可以在 url 中添加参数指定编码,如下:

1
jdbc:mysql://localhost:3306/userinfo?useUnicode=true&characterEncoding=utf-8

user 和 password 即为数据库的用户名和密码。

比如 user 为 root、password 为 12346,那么整个过程如下:

1
2
Class.forName("com.mysql.jdbc.Driver"); // 加载驱动程序
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/userinfo?useUnicode=true&characterEncoding=utf-8", "root", "123456"); // 建立连接

也可以将 url、用户名、密码等信息存储在 web.xml 中当前 servlet 标签下,在 servlet 中读取,比如在 web.xml 中如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<servlet>
<!--servlet-name等其他属性-->

<!-- 存储 mysql 的用户名和密码 -->
<init-param>
<param-name>sql_user</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>sql_psw</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>

在 servlet 中读取:

1
2
String user = getInitParameter("sql_user");
String psw = getInitParameter("sql_psw");

此外,DriverManager.getConnection方法还有两个实现,允许传入 url 的带有 user 和 password 参数或者使用 Properties 配置文件类传入参数来建立连接。

这些方法最终都调用了类中的 private 方法实现:

1
private static Connection getConnection(String url, java.util.Properties info, Class<?> caller)

使用 DataSource 建立Connection

比如使用 MysqlDataSource 类建立一个 Connection:

1
2
3
4
5
6
MysqlDataSource dataSource = new MysqlDataSource();

dataSource.setDatabaseName("userinfo"); // 指定要连接的数据库的名称
dataSource.setCharacterEncoding("UTF-8"); // 指定使用的编码,避免中文乱码

conn = dataSource.getConnection(USER, PSW); // USER 和 PSW 分别为用户名和密码

另外,使用 org.apache.commons.dbcp.BasicDataSource 等开源库可以用 DataSource 建立一个连接池。

connection 使用完毕后应 close 释放资源。

执行语句

有三个相关的类,Statement、PreparedStatement 和 CallableStatement,后两个是 Statement 的子类。三者各有适合的场景。

Statement

Statement 构造的 sql 语句无法带参数,有以下常用方法:

1
ResultSet executeQuery(String sql)

可以返回一个结果集,适合查询操作 select 语句。

1
int executeUpdate(String sql)

适合 insert、update、delete 等操作,返回值为受影响的行数。

1
boolean execute(String sql)

适合执行一个 sql 语句后得到多个结果,或者 sql 语句将执行的操作未知。当得到的第一个结果是一个结果集 ResultSet 时,返回 true;是受影响个数时,返回 false。根据返回值接下来可以调用 getResultSet 方法或者 getUpdateCount 方法。

需要注意的是,注释中特别强调了,PreparedStatement 和 CallableStatement 不能使用此方法。

PreparedStatement

PreparedStatement 的特点是可以带有参数,这样方便重复使用。比如可以构造如下 update 语句:

1
2
3
4
5
6
7
8
String sql = "UPDATE userinfo set user_name = ? WHERE user_id = ?";

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setString(1, "xiaoming");
stmt.setInt(2, 4);

stmt.executeUpdate();

构造的语句 sql 中,两个 ? 是可以替换的参数,使用 setXXX(int parameterIndex, XXX xxx)方法可以将第 parameterIndex 个 ? 替换为需要的值。

需要注意的是,如果要重复使用 PreparedStatement 语句实例传入不同参数,那么应先调用 clearParameters() 方法清楚之前的值。

CallableStatement

CallableStatement 用于调用在数据库中创建的存储过程。

所有的 Statement 对象都应该在使用完毕后 close。