版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
JDBC概述
为了在Java语言中提供对数据库访问的支持,Sun公司于1996年提供了一套访问数据库的标准Java类库JDBC。JDBC的全称是Java数据库连接(Java Database Connectivity)它是一套用于执行 SQL语句的Java API。应用程序可通过这套API连接到关系数据库完成对数据库中数据的査询、更新和删除等操作。
关于JDBC与数据库驱动的关系,请参见下图:
Sun公司在JDBC中定义数据库操作的相关接口而各数据库厂商在其数据库驱动中实现了这些接口。也就是说:Sun公司并没有提供Java语言与各数据打交道的具体API;而是制定了相关的标准和规范;各数据库厂商(比如MySQL,Oracle,DB2等)在其数据库驱动中实现了这些接口(规范)。所以,JDBC屏蔽了Java与不同数据库打交道的细节问题。假如,项目原本使用的是MySQL,在某段时间后换成了Oracle,那我们基本不用去修改原来项目中的SQL语句,只需要把项目中MySQL的数据库驱动切换成Oracle对应的数据库驱动即可。
JDBC操作步骤与核心API
在此介绍在开发过程中使用JDBC常见操作步骤。
第一步:添加jar包
请添加MySQL所需jar包(例如:mysql-connector-java-5.1.7-bin.jar)至Java项目lib文件夹中;图示如下:
关于普通Java项目添加jar包,可另行参考:https://blog.csdn.net/lfdfhl/article/details/126780581
第二步:加载驱动
利用java.sql.DriverManager.registerDriver( )方法加载驱动,例如:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
该方式不但强烈依赖数据库的驱动jar而且会导致驱动被重复注册2次。故,不建议使用该方式而使用反射的方式加载数据库驱动,代码如下:
Class.forName(“com.mysql.jdbc.Driver”);
第三步: 创建连接
利用java.sql.Drivermanager类中的getConnection()方法与数据库建立连接。
语法如下:
DriverManager.getConnection(“jdbc:mysql://数据库地址:端口号/数据库名”,”用户名”, “密码”);
示例如下:
Connection connection = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”,”root”, “root”);
在该语法及其示例中,jdbc表示协议,mysql表示子协议,localhost代表数据库地址,3306表示端口号,mydb表示要连接的数据库;第一个root表示用户名,第二个root表示密码。
DriverManager.getConnection()方法返回的是java.sql.Connection类型的对象。java.sql.Connection是一个接口,它用于与数据库交互;各数据库驱动中均实现了该接口。
第四步:创建PreparedStatement对象
PreparedStatement是Statement的子接口,它可以预编译 SQL 语句并将预编译后的SQL语句存储在PreparedStatement对象中。由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement对象。
在项目开发过程中通常使用java.sql.Connection创建用于执行SQL语句的PreparedStatement;示例如下:
String sql = "Your SQL";
PreparedStatement preparedStatement = connection.prepareStatement(sql);;
Connection的prepareStatement()方法返回的是实现java.sql.PreparedStatement 接口的对象。java.sql.PreparedStatement接口用于操作SQL语句并返回相应的结果集;各数据库驱动中均实现了该接口。
PreparedStatement使用步骤
- 第一步
编写带有?占位符的SQL语句 - 第二步
使用Connection的prepareStatement( )方法和包含了?占位符的SQL语句创建PreparedStatement对象并对SQL语句进行预编译 - 第三步
使用PreparedStatement的setXXX(index , value)方法传入实参取代之前的?占位符 - 第四步
使用PreparedStatement的execute( )、 executeUpdate( ) 、 executeQuery( )方法执行 SQL 语句
总的来说:较Statement而言PreparedStatement中采用的预编译策略使得SQL语句的执行不但高效而且安全。
第五步:执行SQL语句
利用java.sql.PreparedStatement 执行SQL语句,其常用方法如下:
execute( )
该方法可以执行任意SQL语句。当且仅当执行select语句且有返回结果时该方法返回true, 其他情况下该方法返回false
executeUpdate( )
该方法常用于执行DML( INSERT、UPDATE或DELETE)和DDL语句。执行DML语句时返回受SQL语句影响的行数,执行DDL语句时返回0
executeQuery( )
该方法通常执行査询语句,执行后返回代表结果集的ResultSet对象
示例如下:
ResultSet resultSet = preparedStatement .executeQuery( );
在该示例中statement.executeQuery( )方法返回的是实现java.sql.ResultSet接口的对象。
ResultSet接口详细介绍
java.sql.ResultSet用于保存执行SQL语句之后得到的结果集;各数据库驱动中均实现了该接口。ResultSet对外暴露一个游标,该游标默认指向结果集第一行之前。
ResultSet常见方法释义如下:
boolean next()
将游标从当前位置向下移动一行
boolean previous()
将游标从当前位置向上移动一行
void afterLast()
将光标移动到末尾,正好位于最后一行之后
void beforeFirst()
将光标移动到开头,正好位于第一行之前
Object getObject(int columnIndex)
根据序号取值,索引从1开始
Object getObject(String ColomnName);
根据列名取值
int getInt(int colIndex)
以int形式获取ResultSet结果集当前行指定列号值
int getInt(String colLabel)
以int形式获取ResultSet结果集当前行指定列名值
float getFloat(int colIndex)
以float形式获取ResultSet结果集当前行指定列号值
float getFloat(String colLabel)
以float形式获取ResultSet结果集当前行指定列名值
String getString(int colIndex)
以String形式获取ResultSet结果集当前行指定列号值
String getString(String colLabel)
以String形式获取ResultSet结果集当前行指定列名值
Date getDate(int columnIndex)
以Date形式获取ResultSet结果集当前行指定列号值
Date getDate(String columnName)
以Date形式获取ResultSet结果集当前行指定列号值
void close()
关闭ResultSet对象
第六步:处理结果
在从ResultSet中获取到数据库中数据后,我们就将这些数据封装到JavaBean中。在此请注意Java的数据类型与数据库的数据类型的对应关系:
第七步:关闭资源
数据库资源非常宝贵,数据库允许的并发访问连接数量有限。因此,当数据库资源用完后切记释放资源。为了保证资源的释放,常在finally代码块中关闭与数据库操作相关的资源。
JDBC入门案例
在此,通过一个完整的入门案例详细介绍JDBC的使用方式及其注意事项。
创建数据库与表
在MySQL中创建数据库mydb和user表并向表中插入数据。
代码如下:
-- 若存在数据库mydb则删除
DROP DATABASE IF EXISTS mydb;
-- 创建数据库mydb
CREATE DATABASE mydb;
-- 选择数据库mydb
USE mydb;-- 创建user表
CREATE TABLE user(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(40),password VARCHAR(40),email VARCHAR(40),birthday DATE
);
-- 插入数据
INSERT INTO user(username,password,email,birthday) VALUES ('lili','123456','lili@sina.com','1999-12-04');
INSERT INTO user(username,password,email,birthday) VALUES ('dodo','565678','dodo@sina.com','1997-10-07');
INSERT INTO user(username,password,email,birthday) VALUES ('nxnx','246866','nxnx@sohu.com','1992-11-11');
INSERT INTO user(username,password,email,birthday) VALUES ('popo','246851','popo@sohu.com','1999-11-22');
创建Java项目
请在IDEA中创建普通Java项目;图示如下:
请规范地分层分包并添加项目所需的jar包。
编写User类
请在bean下创建User类,该类的属性与user表的字段相对应;代码如下:
package com.cn.bean;import java.util.Date;/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl* * 请注意:java.util.Date与java.sql.Date的关系* java.util.Date是父类* java.sql.Date是子类*/
public class User {private int id;private String username;private String password;private String email;//请注意:Date类型为java.util.Dateprivate Date birthday;public User() {}public User(int id, String username, String password, String email, Date birthday) {this.id = id;this.username = username;this.password = password;this.email = email;this.birthday = birthday;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email+ ", birthday=" + birthday + "]";}}
图示如下:
编写UserDao类
请在dao下创建UserDao类,该类用于对user表进行增删改查。首先,我们来实现一个最简单的功能即查询所有用户。代码如下:
package com.cn.dao;import com.cn.bean.User;
import com.cn.util.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl*/
public class UserDao {// 获取所有用户public ArrayList<User> findAll(){Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;ArrayList<User> list = new ArrayList<User>();try {//加载驱动Class.forName("com.mysql.jdbc.Driver");//建立连接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");//编写SQL语句String sql = "select * from user";//创建PreparedStatementpreparedStatement = connection.prepareStatement(sql);//执行SQLresultSet = preparedStatement.executeQuery();//处理结果resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt("id"));user.setUsername(resultSet.getString("username"));user.setPassword(resultSet.getString("password"));user.setEmail(resultSet.getString("email"));//请注意:getDate()方法返回的类型为java.sql.Dateuser.setBirthday(resultSet.getDate("birthday"));list.add(user);}} catch (Exception e) {e.printStackTrace();} finally {//关闭资源if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}return list;}
}
图示如下:
编写测试类
请在test包下创建测试类TestJDBC01,测试Dao中的方法。在此,先测试UserDao中查询所有用户的方法;代码如下:
package com.cn.test;import com.cn.bean.User;
import com.cn.dao.UserDao;
import java.sql.Date;
import java.util.ArrayList;/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl*/public class TestJDBC01 {public static void main(String[] args) {testFindAll();}// 查找所有用户public static void testFindAll() {UserDao userDao = new UserDao();ArrayList<User> userList = userDao.findAll();for (User u : userList) {System.out.println(u);}}}
图示如下:
测试结果如下:
至此,我们完成了JDBC最基本的操作。
JDBC工具类
通过之前的学习我们对MySQL数据库和JDBC有了一定的了解。但是,在之前的示例中,我们每次操作数据库时都需要加载数据库驱动、建立数据库连接以及关闭数据库连接。为了避免代码的重复书写,我们需利用工具类对JDBC常见操作进行封装方便后续的调用。
请在util包下,创建JDBCUtils类;代码如下:
package com.cn.util;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl*/
public class JDBCUtils {// 加载驱动并建立数据库连接public static Connection getConnection() throws SQLException, ClassNotFoundException {// 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 数据库地址。请注意:请依据实际情况填写数据库名称String databaseUrl = "jdbc:mysql://localhost:3306/mydb";// 数据库用户名。请注意:请依据实际情况填写数据库用户名String username = "root";// 数据库密码。请注意:请依据实际情况填写数据库密码String password = "root";// 获取数据库连接Connection connection = DriverManager.getConnection(databaseUrl, username, password);return connection;}// 关闭数据库连接释放资源public static void release(Connection connection,Statement statement, ResultSet resultSet) {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}}
}
图示如下:
接下来,我们利用此工具类再次查询user表中的所有用户,UserDao中的findAllByUtils( )方法如下:
// 结合数据库操作工具类获取所有用户public ArrayList<User> findAllByUtils(){Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;ArrayList<User> list = new ArrayList<User>();try {//建立连接connection = JDBCUtils.getConnection();//编写SQL语句String sql = "select * from user";//创建PreparedStatementpreparedStatement = connection.prepareStatement(sql);//执行SQLresultSet = preparedStatement.executeQuery();//处理结果resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt("id"));user.setUsername(resultSet.getString("username"));user.setPassword(resultSet.getString("password"));user.setEmail(resultSet.getString("email"));//请注意:getDate()方法返回的类型为java.sql.Dateuser.setBirthday(resultSet.getDate("birthday"));list.add(user);}} catch (Exception e) {e.printStackTrace();} finally {//关闭资源JDBCUtils.release(connection, preparedStatement, resultSet);}return list;}
JDBC增删改查操作
在此,结合JDBC工具类实现对于user表的增删改查操作;UserDao代码如下:
package com.cn.dao;import com.cn.bean.User;
import com.cn.util.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl*/
public class UserDao {// 获取所有用户public ArrayList<User> findAll(){Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;ArrayList<User> list = new ArrayList<User>();try {//加载驱动Class.forName("com.mysql.jdbc.Driver");//建立连接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");//编写SQL语句String sql = "select * from user";//创建PreparedStatementpreparedStatement = connection.prepareStatement(sql);//执行SQLresultSet = preparedStatement.executeQuery();//处理结果resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt("id"));user.setUsername(resultSet.getString("username"));user.setPassword(resultSet.getString("password"));user.setEmail(resultSet.getString("email"));//请注意:getDate()方法返回的类型为java.sql.Dateuser.setBirthday(resultSet.getDate("birthday"));list.add(user);}} catch (Exception e) {e.printStackTrace();} finally {//关闭资源if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}return list;}// 结合数据库操作工具类获取所有用户public ArrayList<User> findAllByUtils(){Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;ArrayList<User> list = new ArrayList<User>();try {//建立连接connection = JDBCUtils.getConnection();//编写SQL语句String sql = "select * from user";//创建PreparedStatementpreparedStatement = connection.prepareStatement(sql);//执行SQLresultSet = preparedStatement.executeQuery();//处理结果resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt("id"));user.setUsername(resultSet.getString("username"));user.setPassword(resultSet.getString("password"));user.setEmail(resultSet.getString("email"));//请注意:getDate()方法返回的类型为java.sql.Dateuser.setBirthday(resultSet.getDate("birthday"));list.add(user);}} catch (Exception e) {e.printStackTrace();} finally {//关闭资源JDBCUtils.release(connection, preparedStatement, resultSet);}return list;}// 添加用户public boolean insert(User user) {Connection connection = null;PreparedStatement preparedStatement = null;try {connection = JDBCUtils.getConnection();String sql = "INSERT INTO user(username,password,email,birthday) VALUES (?,?,?,?)";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, user.getUsername());preparedStatement.setString(2, user.getPassword());preparedStatement.setString(3, user.getEmail());//请注意: setDate()方法第二参数类型为java.sql.DateDate date = new Date(user.getBirthday().getTime());preparedStatement.setDate(4, date);int num = preparedStatement.executeUpdate();if (num > 0) {return true;}return false;} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(connection, preparedStatement,null);}return false;}// 删除用户public boolean delete(int userid) {Connection connection = null;PreparedStatement preparedStatement = null;try {connection = JDBCUtils.getConnection();String sql = "DELETE FROM user WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, userid);int num = preparedStatement.executeUpdate();if (num > 0) {return true;}return false;} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(connection, preparedStatement,null);}return false;}// 修改用户public boolean update(User user) {Connection connection = null;PreparedStatement preparedStatement = null;try {connection = JDBCUtils.getConnection();String sql = "UPDATE user SET username=? , password=? , email=? , birthday=? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, user.getUsername());preparedStatement.setString(2, user.getPassword());preparedStatement.setString(3, user.getEmail());//请注意: setDate()方法第二参数类型为java.sql.DateDate date = new Date(user.getBirthday().getTime());preparedStatement.setDate(4, date);preparedStatement.setInt(5, user.getId());int num = preparedStatement.executeUpdate();if (num > 0) {return true;}return false;} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(connection, preparedStatement,null);}return false;}// 依据id查找用户public User findById(int userid) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {connection = JDBCUtils.getConnection();String sql = "SELECT * FROM user WHERE id = ?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, userid);resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt("id"));user.setUsername(resultSet.getString("username"));user.setPassword(resultSet.getString("password"));user.setEmail(resultSet.getString("email"));//请注意:getDate()方法返回的类型为java.sql.Dateuser.setBirthday(resultSet.getDate("birthday"));return user;}return null;} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(connection, preparedStatement,resultSet);}return null;}
}
TestJDBC01中的测试代码如下:
package com.cn.test;import com.cn.bean.User;
import com.cn.dao.UserDao;
import java.sql.Date;
import java.util.ArrayList;/*** 原创作者:谷哥的小弟* 博客地址:http://blog.csdn.net/lfdfhl*/
public class TestJDBC01 {public static void main(String[] args) {testFindAll();}// 查找所有用户public static void testFindAll() {UserDao userDao = new UserDao();ArrayList<User> userList = userDao.findAll();for (User u : userList) {System.out.println(u);}}// 利用工具类查找所有用户public static void testFindAllByUtils(){UserDao userDao=new UserDao();ArrayList<User> userList = userDao.findAllByUtils();for(User u:userList){System.out.println(u);}}// 增加用户public static void testInsert(){UserDao userDao=new UserDao();User user=new User();user.setUsername("koko");user.setPassword("666666");user.setEmail("koko@sina.com");//请注意Date的类型为java.sql.DateDate birthday= Date.valueOf("1997-07-01");user.setBirthday(birthday);boolean insertResult = userDao.insert(user);if(insertResult){System.out.println("插入操作成功");}else{System.out.println("插入操作失败");}}// 修改用户public static void testUpdate(){UserDao userDao=new UserDao();User user=new User();user.setId(5);user.setUsername("koko");user.setPassword("777777");user.setEmail("koko@sina.com");boolean updateResult = userDao.update(user);if(updateResult){System.out.println("修改操作成功");}else{System.out.println("修改操作失败");}}// 依据id查询用户public static void testFindById(){UserDao userDao=new UserDao();User foundUser = userDao.findById(5);System.out.println(foundUser);}// 删除用户public static void testDelete(){UserDao userDao=new UserDao();boolean deleteResult = userDao.delete(5);if(deleteResult){System.out.println("删除操作成功");}else{System.out.println("删除操作失败");}}}