JDBC
Posted 奔跑的路奇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC相关的知识,希望对你有一定的参考价值。
JDBC
1 JDBC的介绍
1.1 简介
JDBC(Java DataBase Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,(本文中的代码都是针对mysql数据库实现的)。
简单的描述就是可以通过JDBC直接对数据库进行操作。
1.2 JDBC核心组件
- DriverManager: 此类管理数据库驱动程序列表。使用通信子协议将来自java应用程序的连接请求与适当的数据库驱动程序匹配。
- Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用DriverManager对象来管理这种类型的对象。
- Connection:该界面具有用于联系数据库的所有方法。连接对象表示通信上下文,即,与数据库的所有通信仅通过连接对象。
- Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派生接口还接受参数。
- ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一个迭代器,允许我们移动其数据。
- SQLException:此类处理数据库应用程序中发生的任何错误
2 JDBC连接步骤
2.1 注册驱动
注意要先导入对应的mysql连接数据库的jar包
mysql6以下驱动:com.mysql.jdbc.Driver
mysql6和6以上驱动:com.mysql.cj.jdbc.Driver
初始化驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。
2.2 建立JDBC和数据库之间的Connection连接
我这里是写成了方法,后面会有完整的代码演示
private String userName = "root";//用户名
private String passWord = "123456";//密码
//数据库服务端的IP地址:127.0.0.1 (这是本机,如果连接其他电脑上的数据库,需填写相应的IP地址) ;
// demo:是自己的建的数据库名称; serverTimezone=UTC:是时区,如果不写对应版本高的数据库来说会报错
private String url = "jdbc:mysql://localhost:3306/demo?serverTimezone=UTC";
protected Connection getConnection(){
try {
connection = DriverManager.getConnection(url, userName, passWord);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
2.3 执行查询
2.3.1 第一种方式:使用Statement接口
执行查询是使用executeQuery方法
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from employee;"); //executeQuery:执行查询的sql
//4 取出查询到的结果
while (resultSet.next()){
System.out.println("姓名:"+resultSet.getString("name") );
}
执行删除,添加时使用的是executeUpdate,返回的结果是受影响的行数
statement = connection.createStatement();
int i = statement.executeUpdate("update employee set sex='女' where empid=1;");//executeUpdate:执行修改,删除,添加 时使用
//4 判断执行是否成功 i:代表执行sql语句影响的数
if (i>0){
System.out.println("操作成功:"+i);
}else {
System.out.println("操作失败");
}
但注意::使用第一种方式可能会导入有SQL注入的问题
SQL注入:将(恶意的)SQL命令注入到后台数据库引擎执行的能力
例如:
String username = "admin";
String password =" 'abc' or 1=1 ";
String sql ="select * from users where username= '"+username+"' and password= "+password; //不论密码是否输入正确,都会执行成功
2.3.2 第二种方式:使用PreparedStatement接口
该PreparedStatement的接口扩展了Statement接口,它为您提供了一个通用的Statement对象有两个优点附加功能。
String sql = "update employee set sex=? where empid=?";
//使用预编译的语句,防止sql注入
preparedStatement = connection.prepareStatement(sql);
String sex = "女";//要插入的sex
int empid = 1; //插入的id
//给占位符(?)赋值
psm.setString(1,sex); //是从1开始,不是从0
psm.setInt(2,empid);
//执行sql
int i = psm.executeUpdate();
//判断执行是否成功 i:代表执行sql语句影响的数
if (i>0){
System.out.println("操作成功:"+i);
}else {
System.out.println("操作失败");
}
- 使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。
- 后面需要用到PreparedStatement接口创建的pstmt的set方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
- 增删改都使用psm.executeUpdate();语句进行SQL语句的提交
- 查询使用psm.executeQuery();得到的结果是返回查询到的结果集
2.3.3 对比statement和PreparedStatement
(1)statement属于状态通道,PreparedStatement属于预状态通道
(2)预状态通道会先编译sql语句,再去执行,比statement执行效率高
(3)预状态通道支持占位符?,给占位符赋值的时候,位置从1开始
(4)预状态通道可以防止sql注入,原因:预状态通道在处理值的时候以字符串的方式处理
2.4 使用ResultSet处理和显示结果
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from employee;"); //executeQuery:执行查询的sql
//4 取出查询到的结果
while (resultSet.next()){
System.out.println("姓名:"+resultSet.getString("name") );
}
2.5 释放资源
在JDBC编码的过程中我们创建了Connection、ResultSet等资源,这些资源在使用完毕之后是一定要进行关闭的。
需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。
写成了一个方法,可以更好对进行代码复用
protected void closeAll(){
try {
if (connection != null){
connection.close();
}
if (preparedStatement !=null){
preparedStatement.close();
}
if (resultSet != null){
resultSet.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
3 将上述写成完整的工具类
使用的是PreparedStatement,还编写了一个为占位符赋值的setParams方法,在调用增删改方法和查询方法的时候,其内部调用了setParams方法,不用自己赋值
public class JDBCUtil {
Connection connection = null;
PreparedStatement preparedStatement = null;
protected ResultSet resultSet = null;
private int count = 0;
private String userName = "root";
private String passWord = "123456";
private String url = "jdbc:mysql://localhost:3306/kkb1?serverTimezone=UTC";
//1 加载驱动
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//2 获取连接
protected Connection getConnection(){
try {
connection = DriverManager.getConnection(url, userName, passWord);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//3 定义sql , 创建连接通道
protected PreparedStatement getPps(String sql){
try {
getConnection();
preparedStatement = connection.prepareStatement(sql);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return preparedStatement;
}
//4 给占位符赋值,因为参数可以有多个,所有是一个集合形式
protected void setParams(List list){
try {
if (list!=null && list.size()>0){
for (int i = 0; i < list.size(); i++) {
preparedStatement.setObject(i+1 , list.get(i));
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//5 增删改调取的方法; 传入的是sql语句 和 参数
protected int update(String sql , List params){
try {
getPps(sql);
//在执行方法的时候,这里调用了方法为占位符赋值的方法
setParams(params);
count = preparedStatement.executeUpdate();
return count;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return count;
}
//6 执行查询的方法 ,传入的是sql语句 和 参数,没有参数的话,就传入null即可
protected ResultSet query(String sql , List params){
try {
getPps(sql);
//给占位符赋值
setParams(params);
resultSet = preparedStatement.executeQuery();
return resultSet;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//7 关闭资源
protected void closeAll(){
try {
if (connection != null){
connection.close();
}
if (preparedStatement !=null){
preparedStatement.close();
}
if (resultSet != null){
resultSet.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
测试上述方法:
/**
* 根据地址查询对应信息
*/
@Override
public List<AirInfo> getByAddress(String address) {
//一个地址对应可以有多个信息,所以创建集合接收数据
List<AirInfo> lists = new ArrayList<AirInfo>();
try {
String sql = "select * from airinfo where address=?";
//创建的集合是为了存放参数
List list = new ArrayList();
list.add(address);
//执行工具类的查询 , 在query查询方法中,调用了为占位符赋值的方法
ResultSet query = query(sql, list);
//从数据库中查询到的值,赋值给自己创建的bean类
//然后就可以通过getId , getAddress...,得到数据
while (query.next()){
AirInfo airInfo = new AirInfo();
airInfo.setId(query.getInt("id"));
airInfo.setAriId(query.getString("airId"));
airInfo.setAddress(query.getString("address"));
airInfo.setFilDate(query.getString("filDate"));
lists.add(airInfo);
}
} catch (Exception e) {
e.printStackTrace();
}
//返回查询到的结果集合
return lists;
}
/**
* 根据航id更新对应的信息
*/
@Override
public int updateById(String airId, String address, String filDate, int id ) {
int i = 0;
try {
String sql = "update airinfo set airId=?, address=?, filDate=? where id=?";
List list = new ArrayList();
list.add(airId);
list.add(address);
list.add(filDate);
list.add(id);
i = update(sql, list);
} catch (Exception e) {
e.printStackTrace();
}finally {
closeAll();
}
//返回受影响的数
return i;
}
最后,如果有问题,希望指正,一起进步。
以上是关于JDBC的主要内容,如果未能解决你的问题,请参考以下文章