本文主要介绍了Java的JDBC编程的过程. 超详细 !!!
一.JDBC
JDBC就是通过Java代码,来操作数据库
由于我们在实际开发中,绝大部分都是用代码来操作数据库的 , 因此一个成熟的数据库,都会提供一些API让程序员来使用.
常见的数据库比如mysql / oracl / sqlserver / SQLite 都会提供相应的API
但是这些数据库提供的api是否是一样的呢?
不是一样的 ! 每个数据库设计api的人都是不同的 , 这非常不利于程序员的开发 .
于是Java就召集了几个数据库做出了一套统一的api
JDBC就是java提出的一套操作数据库的api , 它让所有的数据库都能够按照统一的方式来操作使用
从此之后,java程序员只需要掌握一套api,就可以操作各种数据库 .
但是JDBC是提供了一套统一的api,但是数据库本身也有自己的原生api,因此这里就需要一个驱动包, 其实是每个数据库厂商提供了一些代码,把数据库原生api进行转化
二.Java代码操作MySQL
1.创建个项目
IDEA新建项目
2.引入mysql的驱动包,作为项目的依赖
首先要将驱动包下载下来,然后导入到项目中
下载mysql驱动包一般有以下几个渠道
a.oracle官方网站
b.github
c.中央仓库(推荐)
中央仓库 (圈子有里的一些大佬把一些知名的第三方库都收集到一起放到了中央仓库,只要去中央仓库找,一般可以找到)
推荐一个好用的中央仓库:
https://mvnrepository.com/
搜索找到这个
选择版本之后点开,点击jar就可以下载驱动包了
.jar是类似于.rar这样的压缩包,是java定义的一种压缩格式
.jar中主要包含了很多的.class文件
3.把驱动包导入到项目中
a.复制jar包到目录中
b.右击add as library (这样idea就知道这个是库文件)
准备工作就做好了,后面就可以编写代码了
三.编写JDBC
1.创建数据源
注意:
此时我们使用向上转型和向下转型,目的是为了降低mysql驱动包和代码之间的耦合关系,避免后续更换数据库的时候有太大的成本 .
因此实际上也可以直接不转型:
- setUrl
设置唯一资源定位符
ip地址:由于此时我们的客户端和服务器都在编写代码的主机上,所以使用127.0.0.1(环回ip)来表示 .
- 设置用户名和密码
到这里就描述了数据库服务器的位置,但是还没有真正连接数据库服务器(建立网络上的连接)
2.连接数据库服务器
注意: 此处的connection使用红框这个 !
第一个是mysql驱动包提供的, 不可以用 ! !
一个java可以连多个数据库服务器,和每个数据库服务器进行通信都得有一个独立connection .
3.构造sql语句
本身SQL语句是string类型, JDBC提供了statement对象,让我们把string转换成statement再发送给服务器执行
但是一般会使用preparedStatement(预处理的语句)对象来代替statement.
*statement把直接把sql发送给数据库服务器 . 数据库服务器自己负责解析SQL
* PreparedStatement会先在客户端这边初步解析以下sql,验证语法格式是否符合要求,此时服务器就不用简称,从而降低了服务器的负担.
4.执行sql语句
executeQuery | 适用于查询 (本质是读) |
executeUpdate | 适用于插入/修改/删除(本质是写) |
返回受影响的行数
5.释放必要的资源,关闭连接
创建的语句对象和连接对象都会持有一些计算机的硬件,软件上的资源,这些资源不用了 , 就应该及时释放
注意:Java虽然有垃圾回收机制,自动释放内存,但是计算机资源不仅仅是内存,其他的资源就需要手动释放 .
注意关闭顺序:
先创建的后关闭; 后创建的先关闭 ;
四.防止sql注入问题
上述实例的插入数据是固定的 , 我们可以尝试用动态输入的数据插入
使用字符串拼接的方式
这个方式可以达成效果,但是不建议这样写
1.看起来混乱
2.不安全 . SQL注入问题. 黑客可能会构造一些特定的输入,达成对数据库攻击的效果
PreparedStatement提供了基于占位符的写法,解决了上述问题
?是一个占位符,占据一个位置,后续preparedstatement会把变量的数值带入到?中
五.代码
1.删除/修改/删除
删除和修改操作与上面的插入操作,代码完全相同,只是构造的SQL语句不一样 , 返回值都是一个简单的整数 ,表示受影响的行数 . (以下代码以插入为例)
Scanner scanner=new Scanner(System.in);
System.out.println("请输入学号");
int id=scanner.nextInt();
System.out.println("请输入姓名");
String name =scanner.next();
//1.创建数据源
DataSource dataSource=new MysqlDataSource();//向上转型:父类引用指向子类对象
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:13306/java? characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("123456");
//2.和数据库服务器建立连接
Connection connection=dataSource.getConnection();
//3.构造sql语句
String sql="insert into test values(?,?)";
PreparedStatement statement=connection.prepareStatement(sql);
statement.setInt(1,id);
statement.setString(2,name);
//4.执行sql 返回影响的行数
int n=statement.executeUpdate();
System.out.println(n);
//5.释放必要资源,关闭连接
statement.close();
connection.close();
2.查询
对于查询来说,返回的是一个临时表 , 需要用结果集resulSet来装 ,取出数据的过程类似于java中的迭代 , 使用如下:
Scanner scanner=new Scanner(System.in);
int id=scanner.nextInt();
//1.创建数据源
DataSource dataSource=new MysqlDataSource();//向上转型:父类引用指向子类对象
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:13306/java?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("123456");
//2.和数据库服务器建立连接
Connection connection=dataSource.getConnection();
//构造sql
String sql="select * from test where id=?";
PreparedStatement statement=connection.prepareStatement(sql);
statement.setInt(1,id);
//4.执行sql
ResultSet resultSet=statement.executeQuery();
//遍历结果集合
while(resultSet.next()){
//获取这一行的学号列
int getid=resultSet.getInt("id");
//获取到这一行的姓名列
String getname=resultSet.getString("name");
System.out.println("学号为"+id+"的同学:"+getid +" " +getname );
}
resultSet.close();
statement.close();
connection.close();
实际上,前面学过的各种复杂的SQL(聚合/多表联合/合并/子查询都是支持的)
总结:
JDBC的api其实还是有一些繁琐的,因此,在Java中,有人就对JDBC进一步封装得到了一些数据库操作的框架(ORM) , 那样就可以简单的操作数据库 .比如,MyBatis框架等