MySQL & Java & JDBC
其实各种各样的语言都可以操控数据库的
例如C, C++, python, Java~
数据库也有很多MySQL便宜好用^v^
这里以MySQL与Java,JDBC编程为例~
特别注意的是:此文章只展现我认为比较好的一种操控方法,其他方法我保持中立~
以下也是我通过简化后的理解~
1. JDBC本质
JDBC ==> Java DataBase Connectivity
Java 数据库连接~
本质上就是一个 API
API ==> Application Programming Interface
应用编程接口,学习完Java后的我们可想而知已经对接口有很大认知了~
没错,Java内置了很多接口类,通过这些接口类,就可以对数据库进行操纵~
Java提供一套标准的API,规定好这些数据库统一的访问方式,数据库厂商按这个要求制作API和对应驱动包~
多个数据库迎合一个语言才比较合理~
但是这些接口有名无实~
必须下载驱动包,即下载配置数据库厂商提供的API和驱动包
JDBC优势:
Java语言访问数据库操作完全面向抽象接口编程
开发数据库应用不用限定在特定数据库厂商的API
他们就是按照咱们的标准做的~
程序的可移植性大大增强
1.1 “.jar文件” – 驱动包下载与配置
jar扩展名也是一种压缩包~
与jdk有关~
点击此链接: mysql-connector-java-5.1.49.jar · 游离态
下载保存到熟悉的地方~
在一个项目的**.idea文件**中建立一个新的目录
命名,我习惯命名为lib(library,在程序员世界里一般指代库的意思~)
将刚才的 “.jar文件”放在这各lib目录下,我用的是Ctrl + C 和Ctrl + V ,将文件中间导入~
确认后将lib目录添加为库~
确认~
OK了~
这样之后就可以正常使用接口了~
2. JDBC编程
2.1 构建数据源
程序与数据库进行联系~
public class Test { public static void main(String[] args) { DataSource dataSource = new MysqlDataSource(); ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/" + /*这里java107含义是数据库名*/"java107?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("我的密码"); } }
2.1.1 MysqlDataSource
普通类实现接口,这是Java程序员的习惯
这个类里有更多的方法,但是太多,我们只需要等一下向下转型用三个设置方法~
2.1.2 setUrl
URL简单来说就是一个这个数据源的定位器
简单的理解为地址呗
程序联系数据库~
“jdbc:mysql://127.0.0.1:3306/java107?characterEncoding=utf8&useSSL=false”
这个复制粘贴就好,现在的知识储备还不能理解~
这里的java107为已存在的数据库的数据库名,我们也可以通过输入字符串,通过字符串拼接
起自定义控制数据库的~
2.1.3 setUser
设置为根用户(root),拥有权限去做后面的事情
2.1.4 setPassword
输入MySQL账户的密码~
密码错误当然进不去~
2.2 用本地数据源建立连接器
Connection connection = dataSource.getConnection();
会报异常
这个异常JVM解决的了~
直接throws或者try catch 去处理~
alt + 回车~
通过这个连接器,就可以跟MySQL服务器交互了~
2.3 通过连接器将SQL语句转化为“准备状态”
通过连接器,建立该语句通往服务器的通道,“准备状态”即一触即发~
SQL语句就是一个字符串对象
String sql = "insert into classes (id, name) values (4, \'软件工程2022级卓越2班\')";
//“增语句”~
//‘ 单引号在java常字符串中,是特殊的,所以要用\去 去除特殊化~
PreparedStatement preparedStatement = connection.prepareStatement(sql);
如果打印这个“准备状态”的话
System.out.println(preparedStatement);
2.4 触发这个准备状态~
2.4.1 非查询语句
这个语句只要不是查询语句,就可以用到这个方法去触发~
包括索引事物甚至创造数据库和表
程序自定义输入信息~
Java提供了个语法,只要在需要自定义信息的位置用“ ?”代替,后续可以处理准备状态的SQL语句,进行自定义~
这个方法很安全,因为通过后续方法插入的信息会被检查~
自定义不代表整条语句交给程序员无限制的自定义
如果通过简单拼接,甚至让程序员输入整条SQL语句的话
如果别有用心,通过特殊语法,从中插入一条删除语句也不是不可能~
这特别危险!
Scanner scanner = new Scanner(System.in); int id = scanner.nextInt(); String name = scanner.nextLine(); preparedStatement.setInt(1, id); preparedStatement.setString(2, name); System.out.println(preparedStatement.executeUpdate());
setInt ==> 设置整数, 参数为 “通配符?”的编号, 填入整数
编号即从左到右 “?” 是第几个~
setString ==> 参数为 “通配符?”的编号, 填入字符串~
2.4.2 查询语句
这个语句只能是查询性质的语句==> 即show语句或者select语句
返回的这个结果集,也是一个迭代器~
并不属于集合类,不能for-each遍历
用类似于迭代器的方法去遍历
String searchSql = "select id, name from classes"; preparedStatement.close(); preparedStatement = connection.prepareStatement(searchSql); ResultSet set = preparedStatement.executeQuery(); while(set.next()) { id = set.getInt("id"); name = set.getString("name"); System.out.println(id + " " + name); }
2.4.2.1 迭代原理
一开始set是处于这个列表头的位置
所以这个时候去获取当前行的数据的时候,必然是会报错的~
set.next( ) 作为循环条件~
set的getxxx方法,获取当前行的信息~
输入的是成员名/别名~
2.5 释放空间
每个客户端这么搞,数据库服务器是有负担的,我们要对这些对象进行释放关闭~
就像吃完饭,要从饭店离开~
后创建的先释放~
否则先创建的对象的释放影响后面的对象的释放~
set.close(); preparedStatement.close(); connection.close();
数据源不需要释放,因为还没跟数据库服务器有联系呢~
3. 知识点补充
3.1 创建数据库
我们现在只是浅浅了解,后续有更多的语法随着我们学习JavaEE,我们会继续完善~
目前我们需要进入一个已知的数据库~
补充知识:show语句虽然没有where语句,但是有like模糊匹配
库名/表明进行模糊匹配~直接作为条件,判断是否输出
通过show语句执行后形成的结果集,判断是否存在此库~(用next方法)
不存在就执行改造数据库~
public static void main(String[] args) throws SQLException { DataSource dataSource = new MysqlDataSource(); ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/" + /*这里java107含义是数据库名*/"java107?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("mmsszsd666"); Connection connection = dataSource.getConnection(); String sql = "show databases like \"newOne\"";//查询性质的语句 PreparedStatement preparedStatement = connection.prepareStatement(sql); ResultSet set = preparedStatement.executeQuery(); if(set.next()) { System.out.println("数据库已存在"); }else{ System.out.println("创建数据库"); preparedStatement.close(); String createSql = "create database newOne charset = utf8"; preparedStatement = connection.prepareStatement(createSql); preparedStatement.executeUpdate(); } set.close(); preparedStatement.close(); connection.close(); }
在数据库那儿进行验证~
3.2 创建表~
思路差不多~
我在newOne中建立一个新表
在释放资源之前调用函数:createNewOne(Connection connection)
public static void createNewOne(Connection connection) throws SQLException { String useSql = "use newOne"; PreparedStatement preparedStatement = connection.prepareStatement(useSql); preparedStatement.executeUpdate(); preparedStatement.close(); String searchSql = "show tables like \"Student\""; preparedStatement = connection.prepareStatement(searchSql); ResultSet set = preparedStatement.executeQuery(); if(set.next()) { System.out.println("已有此表"); }else{ preparedStatement.close(); String sql = "create table Student (id int, name varchar(20))"; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); System.out.println("创建成功"); } set.close(); preparedStatement.close(); connection.close(); }
executeUpdate也可以执行use语句~
在数据库那儿进行验证~
3.3 对于查询语句的结果集
如果一个“准备状态”被执行第二次,上一次的结果集直接强制被释放~
ResultSet resultSet1 = preparedStatement.executeQuery(); ResultSet resultSet2 = preparedStatement.executeQuery(); while(resultSet1.next()) { int id = resultSet1.getInt("id"); String name = resultSet1.getString("name"); System.out.println(id + " " + name); } while(resultSet2.next()) { int id = resultSet2.getInt("id"); String name = resultSet2.getString("name"); System.out.println(id + " " + name); } System.out.println("--------------------------------------------------");
被释放后还去使用必然是会报异常的~