文章目录
- 📑JDBC简介
- 📑通过代码使用JDBC的API
- ☁️结语
📑JDBC简介
实际上在工作中,针对数据库的操作,很少会直接通过命令行/图形化客户端来操作数据库,更多的是通过代码(C++、Java、Python、GO…)
通过代码操作数据库的前提是,数据库首先要提供一组API,供其他的程序来调用
我们知道,数据库有很多种,oracle、MySQL、SQL server…
这些数据库提供的API是不是一样的呢?
不一样!因为这是好几伙人,分别搞的。每个数据库的API都是自成一套体系,苦了咱们广大程序员,程序员一旦切换数据库,就需要学习一套新的API的使用,很麻烦,学习成本高。
API:application programming interface。咱们写代码,一般不是从0开始写的,会调用一些别人写好的代码,别人写好的代码就称为“库”,这些代码里提供的一些类/方法/函数就可以称为API了
但是Java自身指定了一套API标准,各种数据库都要把自己的API转换成和Java这一套兼容的API,咱们Java程序员就省心了,只需要学习一套API就可以应对各种数据库了,这一套API就是JDBC~
每个数据库,本身已经有一套API了,比如MySQL本身的API是C语言的API,MySQL官方提供了一个mysql-connector 这个东西,它可以把MySQL原生api转换成jdbc api这样的过程~
mysql-connector 这个东西也不是Java自带的(第三方库),需要通过第三方的途径,把这个东西下载下来并且导入到自己的项目中。
关于怎么下载mysql-connector,可以看这篇文章:mysql-connector下载教程(手把手)
java中的第三方库,通常是以
.jar
后缀的文件来提供的。称为jar
包~
.jar本质上就是一个类似于.rar这样的压缩包,只不过.jar里放的内容是java的一些.class文件
java代码是.java文件,通过javac编译之后,每个.java就会得到一个.class二进制字节码文件
一个程序可能会有很多类,会有很多.class文件,为了发布方便,于是就可以把这些.class文件打成压缩包,也就是.jar。
我们已经下载好了mysql-connector,那么它该怎么使用呢?
- 先在项目中创建一个目录,名字随便起,但是不要带有中文/特殊字符~
- 把下载好的jar包,拷贝到刚刚的目录中
- 右键刚才的目录,点击add as library。(告诉idea,这个目录是一个“库”目录)
之后再点击ok。
添加完“库”之后,此时idea就能自动分析出jar包里都有啥~
以上这种方式,是一种简单粗暴的方式,适合初学者使用。
实际开发中一般不会这么搞,有更好的方法。
完成上述操作后,我们就可以开始写代码了~
📑通过代码使用JDBC的API
-
创建数据源对象
DataSource
描述了数据从哪里来,以及数据库服务器所在的位置。
DataSource
是一个interface,不能直接new出来,我们需要new出来实习了这个interface的子类~
我们可以new这个子类:DataSource dataSource = new MysqlDataSource();
DataSource 来自java标准库,也就是JDBC自带的接口。
MysqlDataSource 来自我们刚才手动导入的jar包,也就是mysql-connector
因为我们要操控的是MySQL所以new 一个 MysqlDataSource -
给这个对象设置必要的属性
- 数据库服务器在哪里?
- 访问服务器的账户是啥?
- 访问服务器的密码是啥?
这几个部分都是子类拥有的,DataSource本身没有相关的方法和属性~
设置必要属性:
DataSource dataSource = new MysqlDataSource();//这里是向上转型 //为了设置以下这几个属性,又进行了向下转型 ((MysqlDataSource)dataSource).setURL(); ((MysqlDataSource)dataSource).setUser(); ((MysqlDataSource)dataSource).setPassword(); //以上的代码也可以写成: MysqlDataSource dataSource1 = new MysqlDataSource(); dataSource1.setURL(); dataSource1.setUser(); dataSource1.setPassword();
URL
称为“唯一资源定位符”用来描述一个网络上的资源位置,数据库也可以理解成一种网络资源。那么如何写代码呢?
举个例子:
不要被这一长串东西吓倒了,不要背它,我们用到的时候,直接复制粘贴就OK,我们只需要了解他是啥意思就行了~
jdbc:mysql
描述了url 的用途:给jdbc的mysql来使用的
127.0.0.1:3306
是IP地址,描述了mysql服务器所在的主机的位置;mysql 是客户端服务器结构的程序,客户端和服务器之间是通过网络来通信的,此时就通过IP地址这样的概念来描述mysql服务器是在哪个主机上~
127.0.0.1
这个IP是一个特殊的地址,表示“本机”,因为我们jdbc的代码和mysql服务器都是在同一个机器上,此时ip地址就都固定写作127.0.0.1即可,如果是在不同的主机上,再写别的地址。
3306
是端口号,它用来区分一个主机上的应用程序。mysql安装有个步骤可以设置端口号,如果你没有设置过,那就是3306
java112
就是数据库的名字,我们要操作哪个数据库,这里就写那个数据库名。
characterEncoding=utf8&useSSL=false
是额外的参数,起到了针对这次数据库的连接,起到解释说明的作用。utf8
表示使用utf8字符集进行操作。useSSL=false
表示关闭加密。setUser
表示要使用哪个用户
示例:((MysqlDataSource)dataSource).setUser("root");
root是mysql自带的用户,管理员用户,权限是最高的~
setPassword
这里要写入用户的密码。
示例:((MysqlDataSource)dataSource).setPassword("1234");
上面只是在针对数据源对象进行初始化操作,并没有真正和数据库服务器进行任何的网络通信~
-
和数据库服务器建立网络连接
红框里的Connection
对象,就是表示了一个数据库连接。
注意:Connection
的包不要导入错误,我们要导入java.sql
的包 -
连接成功后,我们就可以来用程序构造sql语句了。
构造sql语句的方式有很多种,我们在这里就只介绍一种最主流的方式。
PreparedStatement
:预编译的语句,正常来说,在cmd中敲的sql,是吧sql发送到mysql服务器,mysql服务器负责解析,解析完成之后再执行。解析检查sql是否有语法错误,以及具体要完成什么工作等等,解析工作需要消耗系统资源。由于服务器同一时刻可能要给多个客户端提供服务,解析工作积少成多,也就会比较消耗资源~因此往往就可以把解析工作放到客户端来完成,客户端发送sql之前,先解析好,先把能做好的工作做好,这样就可以降低服务器的工作量,减轻服务器的压力~
示例://此时sql语句中没有 ; 也能区分出这是一个完整的sql String sql = "insert into student values(1,'张三')"; PreparedStatement statement = connection.prepareStatement(sql);
-
把sql语句发送到服务器上进行执行。
我们可以通过statement.execute()
来执行,但是我们一般不会直接用它,而是用statement.executeQuery()
和statement.executeUpdate()
statement.executeQuery()
用来执行查询操作;
statement.executeUpdate()
不仅仅可以用来执行update,还可以执行insert、delete、create table、drop table...它的返回值是int类型,表示执行结果影响到了几行。 -
释放上述的资源
释放资源的顺序要和创建资源的顺序相反! 跟栈有点像。
建立连接\创建语句的时候,需要消耗一定的内存\硬盘\网络等资源…
示例:// 释放资源 statement.close(); connection.close();
在以上的代码中,我们把sql语句写死了,可不可以不写死呢?
当然可以!
有一个简单的做法,我们可以让用户通过控制台在一定程度上输入一个sql语句。
示例:
public static void main(String[] args) throws SQLException {
//让用户输入id和name
Scanner scanner = new Scanner(System.in);
System.out.println("请输入id:");
int id = scanner.nextInt();
System.out.println("请输入name");
String name = scanner.next();
DataSource dataSource = new MysqlDataSource();//这里是向上转型
//为了设置以下这几个属性,又进行了向下转型
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java112?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234");
// 和数据库服务器建立网络连接
Connection connection = dataSource.getConnection();
// 构造sql语句,用字符串拼接的方式来使语句更灵活
String sql = "insert into student values(" + id + ",'" + name + "')";
PreparedStatement statement = connection.prepareStatement(sql);
statement.executeUpdate();
// 释放资源
statement.close();
connection.close();
}
运行上述代码,输入以下内容:
查看数据库:
可以看到student表中成功插入了王五。
虽然上面的代码可以成功执行,但是不建议使用。且听我慢慢分析:
String sql = "insert into student values(" + id + ",'" + name + "')";
像这样拼接字符串不太好
- 代码看起来比较乱
- 可能会引起“sql”注入攻击,可能有人输入的时候不好好输入,故意使坏,就可能使执行sql的时候,产生一定的“负面影响”。比如输入’)drop database xxx;时
为了解决以上的问题,我们可以采用另一种方案:
String sql = "insert into student values(? , ?)";
此处的?
起到了占位符的作用,类似于C语言printf中的 %d。
我们需要将原来代码中的构造sql语句部分换成以下代码就OK啦~
// 构造sql语句
//此时sql语句中没有 ; 也能区分出这是一个完整的sql
String sql = "insert into student values(? , ?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1,id);//把第一个问号替换成id
statement.setString(2,name);//把第二个问号替换成name
这样就完成了问号的替换操作。
注意:
-
选择正确的函数
-
替换第一个问号是从1开始的,而不是0!
为了我们在实际开发中,不一定是直接使用jdbc来操作数据库,但是使用的任何一个操作数据库的框架,底层都是依赖jdbc。
使用update \ delete 的代码完全一样,只需要把String sql 里的内容替换一下~
但是select操作和上述操作不同,它多了一个步骤“遍历结果集合”
示例:
public static void main(String[] args) throws SQLException {
// 1.创建数据库
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java112?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234");
// 2.建立连接
Connection connection = dataSource.getConnection();
// 3.构建sql
String sql = "select * from student";
PreparedStatement statement = connection.prepareStatement(sql);
// 4.执行sql,这一步有所不同
ResultSet resultSet = statement.executeQuery();
// 5.遍历结果集合
while (resultSet.next()) {
//循环里对一行进行处理
System.out.println(resultSet.getInt("id"));//取出id这一列的一个整数,
System.out.println(resultSet.getString("name"));//取出name这一列的一个字符串
}
// 6.关闭对应资源
resultSet.close();
statement.close();
connection.close();
}
5.遍历结果集合
中的代码类似于迭代器操作,每次调用next“光标”就往下移动一行。
注意:在取列的时候,要确保使用的方法和列的类型是匹配的!也要确保列的名字是在查询结果中存在(不一定是原始表存在,查询结果的临时表存在即可)
以上就是本文的全部内容啦~~
☁️结语
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!
都看到这里啦!真棒(*^▽^*)
可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家
如有纰漏或错误,欢迎指正