JDBC概念
JDBC = Java Database Connectivity
JDBC提供服务器与DB的连接方法。一共分为5步完成。
- 加载驱动:数据库只是一个存储的单元,所有的SQL语句都保存在Java中。但是Java无法执行SQL语句,而数据库可以,因此需要将Java中的SQL语句发送到数据库然后执行,因此第一步应该是让Java与数据库之间建立联系。
- 创建连接
- 预编译:分为两小步,首先要实现SQL的定义,来表示接下来要执行的操作;然后将SQL语句发送到数据库中。
- 执行SQL
- 关闭连接
具体步骤
在数据库中创建表
mysql> create table Student(
-> id int primary key not null auto_increment,
-> name varchar(45),
-> score int
-> );
打开Eclipse
新建一个项目,名字叫JDBC_Project,然后需要导入与JDBC相关的jar包。为了方便管理,在项目下新建一个文件夹,命名为lib。然后将jar包复制到文件目录下。此时jar包已经在项目下,而项目还没有编译这个jar包,因此需要手动编译一下。选中该jar包,右键选择Build Path –> add to Build Path。至此,JDBC的准备工作已经完成。
使用JDBC
加载驱动
Java与数据库连接的驱动为com.mysql.jdbc包下的一个叫Driver的类。因此,加载驱动的语句如下:
Class.forName("com.mysql.jdbc.Driver");
创建连接
通过DriverManager类中的getConnection方法创建Java与数据库之间的连接,该方法需要三个参数,分别是数据库的地址、用户名以及密码。这三个参数均为字符串,因此需要先定义这三个参数,然后调用方法创建连接。
String url = "jdbc:mysql://localhost:3306/database_name?characterEncode=utf-8";
String user = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url, user, password);
这个例子中的数据库为本地数据库,因此采用localhost,如果是非本地的数据库,则应该写上数据库对应的IP地址。3306端口是数据库默认的端口,端口后面写上数据库的名字。为了防止出现中文乱码的情况,数据库名字后面携带参数characterEncode=utf-8。注意,这里的等号两边不能有空格。
预编译与执行
预编译的目的在于,在Java端提前备好SQL语句,然后通过调用相应的方法,将现成的SQL语句发送到数据库端进行执行。由于SQL语句不可能是固定的,因此使用问号进行占位。即SQL语句中可能发生更改的地方用问号代替,然后再使用相应的方法替换对应位置的问号。完整这一系列操作之后,通过executeUpdate或者executeQuery方法将SQL语句发送到数据库端。
// 准备SQL语句
String sql = "insert into student(name,score) values (?,?)";
PreparedStatement prepareStatement = connection.prepareStatement(sql);
prepareStatement.setString(1,"张三");
prepareStatement.setInt(2,98);
int executeUpdate = prepareStatement.executeUpdate();
以添加数据为例,添加数据时的名字、分数每次都是不同的,因此用问号占位,然后使用prepareStatement中的setString、setInt等方法替换问号对应的值。然后用executeUpdate方法和executeQuery方法将SQL语句传给数据库。
executeUpdate方法用于对数据的增、删、改,其返回值是整型,表示产生修改的数据的行数;executeQuery方法用于对数据进行查询,其返回值是java.sql包下的ResultSet集合类型,它相当于一个二维表,通过while循环来遍历返回的值。
ResultSet result = prepareStatement.executeQuery();
while (result.next()){
System.out.print(result.getInt("id"));
System.out.print(result.getString("name"));
System.out.println(result.getInt("score"));
}
用next方法可以得知该集合中是否还有值,然后对于不同的值,按照查询语句中字段的顺序及其对应的类型,用getInt、getString等方法进行获取。这些方法的参数就是对应的字段名字。
关闭连接
完成与数据库的交互之后,需要关掉相应的连接。需要关掉的连接包括ResultSet(如果存在的话)、PrepareStatement以及Connection。根据这三个连接创建的顺序,最晚创建的最先关掉。
result.close();
prepareStatement.close();
connection.close();
封装
在实际使用的过程中,有些步骤,例如加载驱动、创建连接、关闭连接等是多次使用,且几乎没有变化的。而且,在加载驱动等过程中涉及到的数据库的地址、账号密码、驱动等等都有一个特点,即易写错且极少更改。因此,可以将这些步骤封装到一个静态类中,每次需要使用的时候调用一下相应的方法即可。如此一来不仅可以避免在重复写代码的过程中发生笔误,也能减少重复代码的编写次数,提高代码的利用率。
// 将加载驱动、创建连接、关闭连接封装到类中
// 数据库的名称为Test,账号为root,密码为123456。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCUtil {
private static final String URL = "jdbc:mysql://localhost:3306/Test?characterEncode=utf-8";
private static final String USER = "root";
private static final String PASSWORD = "123456";
private static final String DRIVER = "com.mysql.jdbc.Driver";
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName(DRIVER);
connection = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return connection;
}
public static void closeAll(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
try {
if (resultSet != null){
resultSet.close();
}
if (preparedStatement != null){
preparedStatement.close();
}
if (connection != null){
connection.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这样在需要加载驱动并创建连接时,直接调用JDBCUtil.getConnection()即可;当完成交互需要关闭连接时,调用JDBCUtil.closeAll()即可。大大减少了工作量。