当前考虑的是使用Java操作MySQL
MySQL的自身是使用C或C++来编写的
如果使用其他语言操作数据库?
数据库服务器是本体,通过代码写的程序,调用MySQL的API实现的是一个客户端,
其他编程语言访问数据库,就只要按照MySQL服务器的要求,构造出对应的网络请求就行了
本质上是在实现一个MySQL的客户端
MySQL的客户端有很多(只要能按照人家MySQL约定的网络请求的格式来构造请求)
MySQL Workbench就是官方的一个图形化客户端程序
Navicat等第三方的图形化客户端程序
连接Connection != 链接Link
总归下来还是SQL语言,就是换个地方敲
JDBC操作
通过Java来操作MySQL
得先得到MySQL的API
可以在MySQL的官网上找到
可惜 自从被Olrea收购了就很难下载
可以去一些其他的“中央仓库”找到相关的API
此驱动不是指平时日常生活中·说的驱动,硬件驱动(也是一个软件,是让操作系统能够通过这个硬件驱动程序向硬件发号施令) 但是术语同样是,driver——>驱动 而下载下来的
.jar文件,则是一个压缩文件(同zip、7z之类),针对java的压缩包
Java操作数据库的
java为了简化操作
封装
数据库种类很多,每个数据库都会提供一组API,不同的数据库提供的API还不一样,只需要关注JDBC提供的API即可,JDBC在底层把不同的数据库的接口给统一起来了
其实,所谓JDBC编程就是在底层操作MySQL客户端
操作
- 将jar包拷贝到项目的某个目录里
- 右键该目录,add as library
后续就可以访问到该jar包中的类了
MySQL是 客户端 和 服务器 结构
但是不是所有的数据库都是这样的 不是!SQL Server Oracle也是这样的,但是SQLite这个数据库就只有客户端
- 创建一个数据源
- 给数据源对象设置一些参数
- 数据库服务器的ip地址
- 数据库服务器的端口号
- 访问的数据库名(操作这个数据库服务器上面的哪个数据集合)
- 用户名
- 密码
```java import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;
/**
- Created with IntelliJ IDEA
- Description:
- User:王瀚晨
- Date:2021-06-01
Time: 21:13 */ public class TestJDBC { public static void main(String[] args) throws SQLException {
//1.先和数据库建立连接// a.创建一个数据源(DataSource)DataSource dataSource = new MysqlDataSource();// b.给数据源设置一些属性(为了告诉代码,数据库服务器在哪呢)//向下转型,一般习惯这么写,有一个好处就是,如果未来需要换一个数据库,改动就会更小//可能性很低奥,只能说java这个圈子的人都魔怔了,过早优化是万恶之源((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/shop?characterEncoding=utf8&useSSL=true");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("123456");// c.通过getConnection方法来和服务器建立连接//这里大概率回失败,main方法抛出异常Connection connection = dataSource.getConnection();//2.拼装SQL语句——>语法与SQL一致//插入数据 注意此处的 ; 加不加都可以String sql = "insert into exam values(10,'张小辉',60,70,80)";//实际上需要的是一个 语句对象//PreparedStatement会帮助我们很方便的动态的构造出一个SQL 来PreparedStatement statement = connection.prepareStatement(sql);//3.执行SQL语句,上边只是给准备好了语句,还没开始呢//这里执行的是insert语句,尽管是insert但是使用executeUpdate来完成//包括delete 和 update 也是使用executeUpdate 来完成//如果当前执行的是select 语句 , 使用executeQuery来完成//此处的int ret 表示的是影响到了几行int ret = statement.executeUpdate();System.out.println("ret = "+ ret);
//4.收尾工作——>释放前边申请到的资源/*** 就算不释放,影响也不大!但最好还是手动释放* 如果没有手动释放的话,可能会出现问题* 容易出现问题的情况:短时间内,反复进行建立连接/创建语句* 原因:MySQL服务器同一时间能处理过来的链接数目是有限的* 如果不是短时间内高很多链接,在一个长跨度的时间内,反复连接,就不会出现问题** 此处手动释放的及时性要高于等待垃圾回收机制自动释放~~*///例如:用于连接的connection//这里考虑到一个顺序问题,遵循先进后出//先申请的,后释放statement.close();connection.close();}
}
手动输入insert```javaimport com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.Scanner;/*** Created with IntelliJ IDEA* Description:* User:王瀚晨* Date:2021-06-01* Time: 21:13*/public class TestJDBC {public static void main(String[] args) throws SQLException {//1.先和数据库建立连接// a.创建一个数据源(DataSource)DataSource dataSource = new MysqlDataSource();// b.给数据源设置一些属性(为了告诉代码,数据库服务器在哪呢)//向下转型,一般习惯这么写,有一个好处就是,如果未来需要换一个数据库,改动就会更小//可能性很低奥,只能说java这个圈子的人都魔怔了,过早优化是万恶之源((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/shop?characterEncoding=utf8&useSSL=true");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("123456");// c.通过getConnection方法来和服务器建立连接//这里大概率回失败,main方法抛出异常Connection connection = dataSource.getConnection();//手动输入Scanner sc = new Scanner(System.in);int id = sc.nextInt();String name = sc.next();int chinese = sc.nextInt();int math = sc.nextInt();int english = sc.nextInt();//2.拼装SQL语句——>语法与SQL一致//插入数据 注意此处的 ; 加不加都可以String sql = "insert into exam values(?,?,?,?,?)";//实际上需要的是一个 语句对象//PreparedStatement会帮助我们很方便的动态的构造出一个SQL 来PreparedStatement statement = connection.prepareStatement(sql);statement.setInt(1,id);statement.setString(2,name);statement.setInt(3,chinese);statement.setInt(4,math);statement.setInt(5,english);//3.执行SQL语句,上边只是给准备好了语句,还没开始呢//这里执行的是insert语句,尽管是insert但是使用executeUpdate来完成//包括delete 和 update 也是使用executeUpdate 来完成//如果当前执行的是select 语句 , 使用executeQuery来完成//此处的int ret 表示的是影响到了几行int ret = statement.executeUpdate();System.out.println("ret = "+ ret);//4.收尾工作——>释放前边申请到的资源/*** 就算不释放,影响也不大!但最好还是手动释放* 如果没有手动释放的话,可能会出现问题* 容易出现问题的情况:短时间内,反复进行建立连接/创建语句* 原因:MySQL服务器同一时间能处理过来的链接数目是有限的* 如果不是短时间内高很多链接,在一个长跨度的时间内,反复连接,就不会出现问题** 此处手动释放的及时性要高于等待垃圾回收机制自动释放~~*///例如:用于连接的connection//这里考虑到一个顺序问题,遵循先进后出//先申请的,后释放statement.close();connection.close();}}

注意:
- 手动拼装SQL不安全!! 为啥呢?
- 假设用户的名字形如,
name = 'asd';drop database shop;——>SQL注入攻击 - 因此使用,PrepareStatement,人家里面的setXXX方法内部做了充分的校验,能够及时的识别出这种SQL注入攻击
- 假设用户的名字形如,
查找
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;/*** Created with IntelliJ IDEA* Description:* User:王瀚晨* Date:2021-06-03* Time: 20:00*///使用JDBC查找数据public class TestJDBC2 {public static void main(String[] args) throws SQLException {//1.和数据库建立连接//创建数据源DataSource dataSource = new MysqlDataSource();//给数据源设置。一些属性((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/shop?characterEncoding=utf8&useSSL=true");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("123456");//建立连接,选java.sql的选项Connection connection = dataSource.getConnection();//拼接SQL语句String sql = "select * from exam";PreparedStatement statement = connection.prepareStatement(sql);//执行SQL语句 查询语句其实会得到一个临时表//所以通过RsultSet就能够获取到需要的表格中的数据ResultSet resultSet = statement.executeQuery();//通过ResultSet获取到结果内容,遍历结果集合//注意这里不同于sc.hasNext()//每次调用next就类似于i++的操作一样//会先获取到当前的记录,并同时把下标后移//当整个结果集合遍历完毕后,next会返回false,遍历结束while(resultSet.next()){//可以获取到当前记录(当前行的每一列)//必须保证列名相匹配int id = resultSet.getInt("id");String name = resultSet.getString("name");double chinese = resultSet.getDouble("chinese");double math = resultSet.getDouble("math");double english = resultSet.getDouble("english");System.out.println(id+","+name+","+chinese+","+math+","+english);}//释放resultSet.close();statement.close();connection.close();}}

注意:
- 请求彼此之间共用一个
DataSource即可,当然不是说不能创建多份,只是没必要 - 假设如果当前的服务器收到的请求数量很多,随之创建的
Connection对象也很多,那么ResultSet和PrepareStatement也会变多 - 但是
Connection创建的开销远远比创建ResultSet和PrepareStatement更大 - 实际上,我们使用的
DataSource,getConnection并不一定每次调用都创建新的连接对象- 目的就是因为简例连接过程开销太大了,能省则省
- 同时又不能把
Connection像DataSource一样只搞一份 - 因此引出了,数据库连接池的概念
- 诸如
DataSource这样的对象我们希望只有一份,之创建一个实例就可以了- 通过单例模式,来保证
DataSource只有一个实例
- 通过单例模式,来保证
单例模式:
是一种设计模式——>例如棋谱
计算机先人们,针对一些经典的场景,设计了一些解决方案
池的概念pool 在计算机中是一个非常广泛使用的概念 进程池、线程池、内存池……
单例模式
线程安全版本的单例模式——>待学习!!
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;public class DBUtil {//类成员 vs 实例成员private static DataSource dataSource = null;//后面再写代码的时候都不适用DataSource直接new了//而是通过下面的getDataSource()方法来获取这个实力public static DataSource getDataSource(){if(dataSource == null){dataSource= new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("");((MysqlDataSource) dataSource).setUser("");((MysqlDataSource) dataSource).setPassword("");}return dataSource;}}
- 操作数据库
- 增加数据
- 删除数据
- 修改数据
- 查询数据
- 约束
- 设计表的方法
- 更加复杂的查找——聚合查询,多表查询,子查询
- 索引/事务
- JDBC编程
注意:
throw是一定会抛出异常
throws是可能会抛出异常
抛出异常,要把close放到finally中,保证其被执行
这时需要了解进程:
- 进程不同于可执行文件,可执行文件只是在磁盘上,双击才跑起来,此时在操作系统中就出现了一个对应的进程
- 进程包含了一系列相关联的资源(内存、文件资源、CPU……)
- 一旦进程被销毁,此时相关的资源也就被回收了
- 在代码中,通过colse方法关闭连接,这是一种比较温和的回收资源的方式
- 如果直接干掉进程,这是一种比较激烈的回收资源的方式
- 实际开发中,进程不是说干掉就能干掉的事情,因为在工作中,涉及到的很多程序对应的进程是一个“服务器进程”
