目录
1.什么是jdbc
2.使用
2.1下载mysql数据库驱动
2.2导入项目
2.3编写代码
2.3.1数据源
2.3.2和数据库服务器建立连接
2.3.3构建一个操作数据库的sql语句
2.3.4执行sql
2.3.5释放前面创建的各种资源
2.3.6运行java程序
2.4其他操作
2.4.1修改操作
2.4.2删除操作
2.4.3查询操作
感谢您的访问!!
在学习完mysql数据库后,学习使用java来操作数据库尤为重要,这篇文章为大家介绍jdbc编程基础
1.什么是jdbc
实际上在我们日常开发中,手动直接操作数据库的情况是比较少的(测试数据,定位bug之类的),更多的是通过java等业务代码来操作
在java中,是通过jdbc这样的技术来操作mysql的
这是因为mysql的底层是c/c++实现的数据库,本身也提供了一些api供程序员调用,从而操控数据库
什么是api?
api,全名是 Application programming interface,即应用程序编程接口,这是一个通用的概念,而不仅仅是局限在java里面.
我们可以把这个词理解成"一组类"或者"一组方法",这都是别人已经写好的,现成的,可以直接调用,就可以实现一些效果
其中,对于java来说,java提供了:标准库,只要你安装了java,就能使用标准库里面的类和方法,即标准库里面的api
但是我们也可以使用其他大佬写好的类和方法,即第三方的库
当然在其他的编程语言也同样有自己的库,也能使用第三方的api
有的库,提供的api特别多,就现成了一个体系,这种情况,也可以称为"SDK"(软件开发工具包),java中的sdk就是jdk
而不仅仅是mysql,其他的数据库比如oracle,sql server.sqlite...都提供了这样的api供程序员调用
但是这样就会出现一个问题:
不同的数据库提供的api是不同的,虽然提供的功能大同小异,但是细节上差异还是非常大的.这样程序员学习的成本就会很高
这时java就提供了一套api标准接口,就让不同的数据库都按照java提供的api适配过来,就是让每个数据库都额外写一些代码,能够按照java提供的这一套标准把原来的原生api重新封装一下.后续程序员在使用的时候,只需要掌握java提供的这套api,就能适配到其他数据库了
那么这一套api就是jdbc
其中,像这样的接口转化程序,被称为"数据库驱动"
JDBC是java标准库提供的,只要安装了jdk就能使用,但是jdbc要想操作数据库就要下载并导入mysql的驱动包
这个.jar文件,实际上就是类似于.rar一样的压缩包文件,这里包含了许多.class这样的文件(.java编译出来的字节码文件)
写好的java文件,就可以把编译出来的.class文件拷贝给别人,别人就能正常运行使用了
但是一个程序中往往会有很多.class文件,涉及很多复杂度目录结构,直接拷贝一堆.class文件不太好
于是就约定把这些要发布的.class文件按照特定格式打包压缩,就得到了.jar文件,后续直接拷贝.jar文件即可.并且jvm可以识别.jar文件的内部的.class文件并直接运行
.jar文件是最常见的一种发布java程序的方式
2.使用
2.1下载mysql数据库驱动
直接去中央仓库下载即可:https://mvnrepository.com/
由于我用的是mysql5.7,那么这里就下载旧版本即可
往下拉就会看到适配5版本的驱动:
点击即可下载
但是我们会看到下面有个警告:
漏洞!!但是对于我们自己的数据库实际上没啥关系
直接下载即可
2.2导入项目
在java项目中随便创建一个目录
将刚刚下载的驱动放到里面去
此时我们要右键这个目录:
这样的操作是告诉idea,当前这个目录是存放第三方的目录,此时idea就能够识别到我们拷贝进来的驱动包了
这样刚刚的驱动就能直接展开了
上述就是jdbc程序的准备工作,那么接下载我们就可以编写代码了
2.3编写代码
要想编写jdbc,还需要准备好数据库和数据表(虽然jdbc也能进行建表操作,但是一般都是在数据库中就已经创建好的)
2.3.1数据源
即要操作的数据库,数据是在哪里
那么在mysql中就要设置好访问数据库的名字,访问数据库的用户名和密码
但是这个dataSourse是jdbc自带的接口,但是接口是不能new实例的
这个类就来自于mysql的驱动包
这个过程就类似:数据库厂商和jdbc进行对接,就是让数据库厂商实现jdbc中提供的一些接口,进一步实现其中约定好的抽象方法
但是实际上:
MysqlDataSource mysqlDataSource = new MysqlDataSource();
也是可以的
但是更多的是第一种写法,因为这便于代码和数据库之间的"解耦合"
万一未来有一天需要变更数据库,第一种代码的写法,改动成本就低一点,即后续使用数据源的时候,看到的都是dataSourse类型,至于里面实际上的数据库是什么就不知道了,这样更加便于切换数据库,反之,如果采用mysqlDataSourse这种写法,就可能会经常涉及到MysqlSourse这样的概念,就会使得后续的修改更加复杂
这时候通过url连接到mysql数据库,就要向下转型回来了
其中这里的url是:唯一资源定位符,我们的客户端要通过网络访问到数据库服务器进行操作,那么url就描述了服务器/服务器上的资源在网络中所在的位置
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
URl:协议的名称://ip地址:端口号/数据库名?参数=值&参数=值
实际上这一串不需要背下来,后续需要直接拷贝即可
实际上mysql可以手动创建各种数据库用户名,默认会带一个root用户(指的是一个管理员账户(权限最大))
下面的密码就是你的数据库密码
这里为什么要向下转型回来??
因为dataSourse是要能够对接到不同的数据库的,而不同的数据库实际上设置数据源的方式是不一样的,对于mysql是url,user,password,但是对于其他的就不一定了
2.3.2和数据库服务器建立连接
进行客户端-服务器之间的通信的时候,常见的有两种通信方式
(1)有连接(jdbc就属于有连接):类似于打电话,拨号后需要对方接听
(2)无连接:类似于发短信
Connection connection = dataSource.getConnection();
需要声明异常
注意:这里的connection要选择sql的,
那么这个Connection对象,就表示客户端与服务器之间的:连接对象
但是实际上在getConnection是很可能失败的(服务器没有接受连接)
原因包括但是不限于:
(1)数据库服务器没有正常启动
(2)url写错了
(3)用户名写错了
(4)密码写错了
(5)网络断开了
....
2.3.3构建一个操作数据库的sql语句
虽然是通过java来操作数据库,但是实际上核心还是sql,只不过把sql嵌套在java中
String sql = "insert into jdbctest values(1,'张三')";
此时还需要一个语句对象
有这两种方式
第一个仅仅是代表一个普通的语句对象,但是第二个则是一个带有"预编译"功能的语句对象
把一个字符串的sql发生到数据库服务器上,是先要对sql进行解析以及各种校验(判定sql是否符合语法要求等),而这样的操作是需要一定开销的,虽然这个开销不大,但是一个数据库服务器往往是要同时给多个客户端提供服务的
因此为了减轻数据库服务器的负担,就可以在客户端这边完成检验
//语句对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
2.3.4执行sql
把刚刚解析好sql语句发生给数据服务器进行操作了
实际上偶遇两种方式:
对于insert,updata.delete统一都是executeUpdate,而selet就是executeQuery
我们这里先进行插入操作
int n = preparedStatement.executeUpdate();
这里的返回值是一个int类型,表示这个操作影响了几行数据
通过执行这个方法,就会在内部给数据库服务器发起请求,请求中就是包含解析后的sql,等待数据库执行sql,过一会执行完后数据库返回响应,这个方法再获取响应,通过返回值的方式体现出来
2.3.5释放前面创建的各种资源
主要是释放语句对象和连接对象,注意:dataSourse是不必释放的
在java中有垃圾回收机制(GC),可以自动帮我们回收我们不用的内存
但在编程过程中涉及到的有限资源不仅仅是内存
如果是内存,那么GC自动回收
但如果是其他资源,java无能为力,就需要手动释放了
注意这里的释放顺序,要确保先创建的后释放
2.3.6运行java程序
但是在这里,当前插入的内容是在代码中写死的
如果想要插入不同的数据就需要修改代码重新编译,但是很多时候是需要在程序运行的时候让用户自己插入数据的
拼接字符串
int id = scanner.nextInt();
String name = scanner.nextLine();
String sql = "insert into jdbctest values(" + id + ",'" + name + "')";
//语句对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
这样就能完成预期效果了
但是实际上这种方式不可行
首先可读性非常差,很容易拼错;其次也不太安全,可能会引起sql注入攻击这样的漏洞
还是比较推荐使用prepareStatement提供的api来完成动态内容的设置
int id = scanner.nextInt();
String name = scanner.nextLine();
String sql = "insert into jdbctest values(?,?)";
//语句对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,id);//表示第一个问号
preparedStatement.setString(2,name);
这种方式jdbc内部会进行校验,避免上述危险操作
2.4其他操作
2.4.1修改操作
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
//数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("2222");
//建立联系
Connection connection = dataSource.getConnection();
//构造sql
int id = scanner.nextInt();
String name = scanner.nextLine();
String sql = "update JDBCTest set name = ? where id = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(2,id);
statement.setString(1,name);
//执行sql
int n = statement.executeUpdate();
System.out.println(n);
//释放资源
statement.close();
connection.close();
}
2.4.2删除操作
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
//数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("2222");
//建立连接
Connection connection = dataSource.getConnection();
//构造sql
int id = scanner.nextInt();
String sql = "delete from jdbcTest where id = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1,id);
//执行sql
int n = statement.executeUpdate();
System.out.println(n);
//释放资源
statement.close();
connection.close();
}
2.4.3查询操作
查询操作又和其他的不太一样
前面的操作都是一样的,但是在执行sql语句的时候
//构造sql语句
String sql = "select * from jdbcTest";
PreparedStatement statement = connection.prepareStatement(sql);
//执行sql语句
ResultSet resultSet = statement.executeQuery();
这里会返回一个结果集合
我们需要通过resultSet.next来得到里面的数据
ResultSet resultSet = statement.executeQuery();
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println(id);
System.out.println(name);
}
这个next就像一个指针,一开始是指向数据的上方,后面会往下走,直到数据遍历完
注意:在最后释放资源的时候,要释放resultSet
//释放资源
resultSet.close();
statement.close();
connection.close();
//查询
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
//数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("051215");
//建立连接
Connection connection = dataSource.getConnection();
//构造sql语句
String sql = "select * from jdbcTest";
PreparedStatement statement = connection.prepareStatement(sql);
//执行sql语句
ResultSet resultSet = statement.executeQuery();
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println(id);
System.out.println(name);
}
//释放资源
resultSet.close();
statement.close();
connection.close();
}