1. 什么是JDBC
JDBC,即Java Database Connectivity,java数据库连接.是一种用于执行SQL语句的Java API,它是 Java中的数据库连接规范.这个API由 java.sql.*,javax.sql.* 包中的一些类和接口组成,它为Java 开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问.
简要来说,JDBC作为桥梁将JAVA代码和数据库连接起来,使得程序猿可以通过操作JAVA代码做到对于数据库的一些操作.
2. JDBC的使用流程
2.1 准备数据库驱动包
在项目中创建文件夹lib,将将依赖包mysql-connector-java-5.1.47.jar复制到lib中.(ctrl+c,ctrl+v).再右键lib,点击Add as library.
配置好jar包,应该呈现下图情况,IDEA告诉我们已经识别出了jar包,可以进行下一步.
2.2 设置数据源
2.2.1 dataSource
首先,我们需要创建一个数据源:dataSource.这里我们使用的是mysql,因此实例化一个MysqlDataSource对象,但是要进行向上转型,用一个DataSource引用来接收.(导包只需要根据报错Alt+Enter导入即可)
DataSource dataSource = new MysqlDataSource();
原因非常简单,JDBC应该可以为多种关系型数据库提供统一访问,现在可能我们使用的是mysql,如果我们后期需要使用到其他数据库,使用向上转型的方式可以极大程度地减少代码的重构成本.
接着,毕竟当下我们使用的是mysql,在使用dataSource时需要强转为MysqlDataSource类型.我们通过这个dataSource来设置三个重要的量:Url,User,PassWord.
2.2.2 Url
URL 代表着是统一资源定位符(Uniform Resource Locator)。URL 无非就是一个给定的独特资源在 Web 上的地址。理论上说,每个有效的 URL 都指向一个唯一的资源。在这里我们先给出代码:
((MysqlDataSource) dataSource).setUrl(
"jdbc:mysql://127.0.0.1:3306/lzq?characterEncoding=utf8&useSSL=false");
Url的构成:"jdbc:数据库名称://默认的网络地址:端口号/需要操作的数据库?限定的字符集&不使用SSL)
这里面最重要的是,我们需要操作的数据库的名称,如果数据库的名称不对或者不存在对应数据库,就会报错.
2.2.3 User
对于User,在我们自己本地操作默认设置为root即可.
((MysqlDataSource) dataSource).setUser("root");
2.2.4 PassWord
这里的PassWord,要与我们之前在安装mysql时设置的客户端密码相同,否则会报错.
((MysqlDataSource) dataSource).setPassword("111111");
2.3 建立连接
建立连接只需要非常简单的一行代码:
Connection connection = dataSource.getConnection();
但是这里面需要我们仔细核对Connection来自于哪个包:
我们必须选择来自java.sql下的Connection!!!否则会报错,而且错误不容易排查!!!
2.4 创建sql语句
这里我们有两种sql语句的写法:
我们以给student表(id int,name varchar(40))插入一条记录为例.
- 直接将所需的字段填入语句
Scanner scanner = new Scanner(System.in);
int id = scanner.nextInt();
String name = scanner.nextLine();
String sql = "insert into student values("+id+","+name")";
这种写法看起来有点别扭,主要是有许多符号(括号,双引号,逗号)被硬生生地分割了,同时它们还聚合在一起,看起来比较费力.
- 先将需要填入的字段用?(占位符)占位,后续再操作
String sql = "insert into student values(?,?)";
之后怎么处理呢,我们要用到接下来介绍的东西.
2.5 执行sql语句
要执行sql语句,我们需要一个statement对象,但是statement对象每次使用时都需要进行编译,十分耗费时间.因此我们就可以使用preparedStatement(预编译的statement对象),可以通过connection的prepareStatement方法得到.
PreparedStatement preparedStatement = connection.prepareStatement(sql);
有了preparedStatement对象之后,我们来解决之前的问题.preparedStatement内置了设置字段的方法
preparedStatement.setInt(1,id);
preparedStatement.setString(2,name);
我们可以根据插入字段的不同类型,调用对应的set_方法,当传入的参数类型不符合时,编译会报错.
使用时还需要注意,对应占位符的下标从1开始.
对比这两种方法:第二种方法更优.
- 增加了安全性,会确保参数的合法性.
- 在视觉上较为舒适,便于排查sql语句中可能出现的语法错误.
2.6 获得结果
接着,如果我们将CRUD的操作分为两类:
2.6.1 Create(增).Update(改).Delete(删)
对于这三种操作,都对数据库中的表做了一定的修改,我们可以使用如下语句,得到一个int类型的返回值:
int n = preparedStatement.executeUpdate();
System.out.println(n);
这里n接收的返回值,代表这个操作影响了表中的几行,如果操作的对象不存在(例如删除一条不存在的记录),这里的n就没有办法正常地打印出来.
2.6.2 Retrieve(查)
对于查询操作,并没有对数据库中的表进行修改,查询出来的只是一张临时表,可以使用如下语句:
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id = "+id+", name = "+name);
}
executeQuery这个方法得到的返回值是一个结果集,并不能直接打印出来,可以通过循环+指定字段来逐条记录打印.
2.7 收尾工作
在使用preparedStatement和connection之后,我们要进行资源的回收,即调用preparedStatement和connection的close方法.注意:通常来说,回收顺序与创建顺序相反,先创建preparedStatement对象,再创建connection对象,因此应该先回收connection对象,再回收preparedStatement对象.但dataSource对象可以反复利用,不必进行回收.
3.JDBC优缺点分析
优势:
- Java语言访问数据库操作完全面向抽象接口编程
- 开发数据库应用不用限定在特定数据库厂商的API
- 程序的可移植性大大增强
不足:
相较于Mybatis等支持自定义数据库的框架操作比较繁琐,开发的效率大打折扣.
4.基于JDBC实现CRUD
将每个操作做成一个类,使用JDBC进行操作,这里直接给出代码:
程序主体:
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
public class main {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
//1.设置数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/lzq?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("111111");
//2.建立连接
Connection connection = dataSource.getConnection();
//3.构造sql语句
System.out.print(
"1.增: insert into sign1(tableName) values(sign2(id),sign3(name));\n" +
"2.删:delete from sign1(tableName) where sign2(condition);sign3为null\n" +
"3.改:update sign1(tableName) set sign2(update) where sign3(condition); \n" +
"4.查:select sign1(sign) from sign2(tableName) where sign3(condition);\n"
);
System.out.println("choice = ");
int choice = scanner.nextInt();
System.out.println("sign1 = ");
String sign1 = scanner.next();
System.out.println("sign2 = ");
String sign2 = scanner.next();
System.out.println("sign3 = ");
String sign3 = scanner.next();
Operation[] operation = {new Create(sign1,sign2,sign3),new Delete(sign1,sign2,sign3),
new Update(sign1,sign2,sign3),new Retrieve(sign1,sign2,sign3)};
String sql = operation[choice-1].operation();
//4.执行sql,把解析后的sql语句发送给服务器
PreparedStatement preparedStatement = connection.prepareStatement(sql);
if(choice == 4) {
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id = "+id+", name = "+name);
}
}else {
int n = preparedStatement.executeUpdate();
System.out.println(n);
}
//5.收尾操作
preparedStatement.close();;
connection.close();
}
}
Operation接口:
public interface Operation {
String operation() ;
}
Create类:
public class Create implements Operation{
String id;
String name;
String tableName;
public Create(String tableName ,String id,String name) {
this.tableName = tableName;
this.id = id;
this.name = name;
}
@Override
public String operation() {
return "insert into "+tableName+" values("+id+",'"+name+"')";
}
}
Retrieve类:
public class Retrieve implements Operation{
String sign;
String condition;
String tableName;
public Retrieve(String sign,String tableName,String condition) {
this.tableName = tableName;
this.sign = sign;
this.condition = condition;
}
@Override
public String operation() {
return "select " + sign + " from " + tableName + " where " + condition;
}
}
Update类:
public class Update implements Operation{
String update;
String condition;
String tableName;
public Update(String tableName,String update,String condition) {
this.tableName = tableName;
this.update = update;
this.condition = condition;
}
@Override
public String operation() {
return "update "+tableName+" set "+update+" where "+condition;
}
}
Delete类:
public class Delete implements Operation{
String empty;
String condition;
String tableName;
public Delete(String tableName,String condition,String empty) {
this.empty = empty;
this.condition = condition;
this.tableName = tableName;
}
@Override
public String operation() {
return "delete from "+tableName+" where "+condition;
}
}
结合了多态的思想,基于JDBC实现了CRUD的操作.