第一章 JDBC概述
之前我们学习了JavaSE,编写了Java程序,数据保存在变量、数组、集合等中,无法持久化,后来学习了IO流可以将数据写入文件,但不方便管理数据以及维护数据的关系;
后来我们学习了数据库管理软件MySQL,可以方便的管理数据1。
那么如何将它俩结合起来呢?即Java程序<==>MySQL,实现数据的存储和处理。
答案:使用JDBC技术,后期可以使用MyBatis等持久层框架(底层仍然使用了JDBC)。
1.1 JDBC概述
JDBC:Java Database Connectivity,它是代表一组独立于任何数据库管理系统(DBMS)的API,声明在java.sql与javax.sql包中,是SUN(现在Oracle)提供的一组接口规范。由各个数据库厂商来提供实现类,这些实现类的集合构成了数据库驱动jar。
即JDBC技术包含两个部分:
(1)java.sql包和javax.sql包中的API
因为为了项目代码的可移植性,可维护性,SUN公司从最初就制定了Java程序连接各种数据库的统一接口规范。这样的话,不管是连接哪一种DBMS软件,Java代码可以保持一致性。
(2)各个数据库厂商提供的jar
因为各个数据库厂商的DBMS软件各有不同,那么内部如何通过sql实现增、删、改、查等管理数据,只有这个数据库厂商自己更清楚,因此把接口规范的实现交给各个数据库厂商自己实现。
/*
一、JDBC的概述
1、之前学习了Java,又学习了MySQL数据库
JDBC 把 Java程序 和 MySQL数据库连起来,Java程序是负责数据的输入,业务的处理,数据的显示,MySQL负责数据的存储和管理。
2、JDBC:Java Database Connectivity
JDBC = JDK核心类库中的一套API(接口+部分工具类) + 数据库厂商提供的驱动jar
Java程序不仅仅能够连接MySQL数据库,可以连接很多数据库(Oracle,SQL Server,DB2,...)。
这就有一个问题?
数据库不同,它们的操作方式会有所不同,因为它们的底层实现方式,实现的语言等都是不同的。
那么Java去连接不同的数据库时,就会有不同的API。这样的话,就会导致:
(1)程序员的学习成本增加
(2)如果发生数据库迁移,Java代码就需要“重写”
如果是这样的话,就非常麻烦,可移植性、可维护性等非常差。
SUN公司(现在Oracle)就说,必须统一一套API,可以操作各种数据库。但是SUN公司又不同知道所有数据库内部是如何实现的,
也无法要求所有的数据库厂商按照统一的标准来开发他们的数据库软件。
SUN公司(现在Oracle)就设计了一套接口 + 部分类。然后各个数据库厂商,来提供这些接口的实现类。
==>Java程序中面向接口编程,在程序运行时,又需要引入这些接口的实现类,这些实现类就是数据库驱动jar。
*/
public class TestJDBC {
}
1.2 Java程序连接MySQL数据库
1.2.1 引入mysql驱动jar
方式一:单独某个模块使用mysql驱动
(1)在模块路径下建一个文件夹“jdbclibs”,把mysql的驱动jar放到里面
MySQL5.7:mysql-connector-java-5.1.36-bin.jar
MySQL8.0:mysql-connector-java-8.0.19.jar
(2)在jdbclibs文件夹上右键-->Add as Library...
(3)填写库名称、选择这个库应用范围(模块)-->选择使用的具体模块
方式二:项目下多个模块使用mysql驱动
(1)在项目路径下建一个文件夹“jdbclibrary”,把mysql的驱动jar放到里面 mysql-connector-java-5.1.36-bin.jar MySQL8.0:mysql-connector-java-8.0.19.jar (2)项目设置-->libraries--> + ->java-->文件夹“jdbclibs” (3)选择需要这个jar的模块 项目设置-->modules-->模块名-->dependencies--> + - >library->Java -> 库
后期其他模块也要使用mysql驱动,可以直接添加项目的jdbclibrary库即可:
方式三:使用Maven仓库(后期大家学习) - 最多!!!
1.2.2 Java代码连接MySQL数据库
/*步骤:
1、模块添加了依赖的mysql驱动相关库
2、在内存中加载驱动类(可选)
更早版本mysql驱动类:org.gjt.mm.mysql.Driver
最近版本:com.mysql.jdbc.Driver
MySQL8.0版本:com.mysql.cj.jdbc.Driver
//新版的mysql驱动jar可以省略这步,旧版的mysql驱动jar必须加这一步。
// 因为新版mysql驱动jar包下有一个META-INF/services/java.sql.Driver文件
//里面有填写mysql驱动类的全名称,DriverManager会自动读取这个文件,并加载对应的驱动类
//后期使用数据库连接池,或者MyBatis等框架时,在配置文件中加这个驱动类的配置即可
Class.forName("com.mysql.cj.jdbc.Driver");
3、连接数据库:通过DriverManager工具类获取数据库连接Connection的对象。
此时的Java程序是MySQL的一个客户端
连接数据库:
MySQL服务器主机的IP地址:
端口号
用户名
密码
网址:http://www.haogu.com
String url = "jdbc:mysql://localhost:3306/test?serverTimezoneAsia/Shanghai";
Connection conn = DriverManager.getConnection(url, "root", "123456");
MySQL8使用时,url需要加参数:serverTimezone=Asia/Shanghai,否则会报错:
Exception in thread "main" java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.
4、断开连接:使用close方法。
*/
import java.sql.Connection;
import java.sql.DriverManager;
public class TestJDBC {
public static void main(String[] args)throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/haogu?serverTimezone=Asia/Shanghai","root","123456");
System.out.println("conn = " + conn);
conn.close();
}
}
1.3 实现增删改查
/*步骤:
1、模块添加了依赖的mysql驱动相关库
2、在内存中加载驱动类(可选)
Class.forName("com.mysql.cj.jdbc.Driver");
3、连接数据库
通过DriverManager工具类获取数据库连接Connection的对象。
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
Connection conn = DriverManager.getConnection(url, "root", "123456");
4、操作数据库
(1)通过Connection对象获取Statement或PreparedStatement对象
(2)通过Statement或PreparedStatement对象执行sql
执行增、删、改:int executeUpate()
执行查询:ResultSet executeQuery()
(3)如果服务器有查询结果返回,需要用ResultSet接收
遍历结果集的方法:
boolean next():判断是否还有下一行
getString(字段名或序号),getInt(字段名或序号),getObject(字段名或序号)
5、释放资源(close)
*/
1.3.1 添加数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
/*
用JDBC实现添加一条记录到haogu数据库的t_department表中。
mysql> desc t_department;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| did | int | NO | PRI | NULL | auto_increment |
| dname | varchar(20) | NO | UNI | NULL | |
| description | varchar(200) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> select * from t_department;
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 研发部 | 负责研发工作 |
| 2 | 人事部 | 负责人事管理工作 |
| 3 | 市场部 | 负责市场推广工作 |
| 4 | 财务部 | 负责财务管理工作 |
| 5 | 后勤部 | 负责后勤保障工作 |
| 6 | 测试部 | 负责测试工作 |
+-----+--------+------------------+
6 rows in set (0.00 sec)
步骤:
1、一个项目引入一次数据库驱动jar就可以
2、建立数据库连接
(1)加载驱动类:通过Class类的forName方法注册驱动
(2)获取数据库连接
通过DriverManager类的静态方法获取数据库连接对象
3、通过数据库连接对象获取Statement或PreparedStatement对象,用来执行sql
4、通过Statement或PreparedStatement对象调用
(1)int executeUpdate():执行insert,update,delete等更新数据库数据的sql
5、关闭,释放各种资源
*/
public class TestInsert {
public static void main(String[] args)throws Exception {
//把驱动类加载到内存中
Class.forName("com.mysql.cj.jdbc.Driver");
//B:获取数据库连接对象
String url = "jdbc:mysql://localhost:3306/haogu?serverTimezone=Asia/Shanghai";
Connection connection = DriverManager.getConnection(url,"root","123456");
//Connection ==> 网络编程的Socket
String sql = "insert into t_department values(null,'测试数据部门','测试数据部门简介')";//发给服务器的sql
PreparedStatement pst = connection.prepareStatement(sql);
//PreparedStatement ==> IO流 网络编程的socket.getOutputStream()发生数据用的
int len = pst.executeUpdate();
//返回sql影响的记录数
System.out.println(len>0 ? "添加成功" : "添加失败");
pst.close();
connection.close();
/*
mysql> select * from t_department;
+-----+--------------+------------------+
| did | dname | description |
+-----+--------------+------------------+
| 1 | 研发部 | 负责研发工作 |
| 2 | 人事部 | 负责人事管理工作 |
| 3 | 市场部 | 负责市场推广工作 |
| 4 | 财务部 | 负责财务管理工作 |
| 5 | 后勤部 | 负责后勤保障工作 |
| 6 | 测试部 | 负责测试工作 |
| 7 | 测试数据部门 | 测试数据部门简介 |
+-----+--------------+------------------+
7 rows in set (0.00 sec)
*/
}
}
1.3.2 修改数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TestUpdate {
public static void main(String[] args)throws Exception {
//把驱动类加载到内存中
Class.forName("com.mysql.cj.jdbc.Driver");
//B:获取数据库连接对象
String url = "jdbc:mysql://localhost:3306/haogu?serverTimezone=Asia/Shanghai";
Connection connection = DriverManager.getConnection(url, "root", "123456");
//Connection ==> 网络编程的Socket
String sql = "update t_department set description = 'xx' where did = 7";//发给服务器的sql
PreparedStatement pst = connection.prepareStatement(sql);
//PreparedStatement ==> IO流 网络编程的socket.getOutputStream()发生数据用的
int len = pst.executeUpdate();
//返回sql影响的记录数
System.out.println(len > 0 ? "修改成功" : "修改失败");
pst.close();
connection.close();
}
}
/*
mysql> select * from t_department;
+-----+--------------+------------------+
| did | dname | description |
+-----+--------------+------------------+
| 1 | 研发部 | 负责研发工作 |
| 2 | 人事部 | 负责人事管理工作 |
| 3 | 市场部 | 负责市场推广工作 |
| 4 | 财务部 | 负责财务管理工作 |
| 5 | 后勤部 | 负责后勤保障工作 |
| 6 | 测试部 | 负责测试工作 |
| 7 | 测试数据部门 | xx |
+-----+--------------+------------------+
7 rows in set (0.00 sec)
*/
1.3.3 删除数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TestDelete {
public static void main(String[] args)throws Exception {
//把驱动类加载到内存中
Class.forName("com.mysql.cj.jdbc.Driver");
//B:获取数据库连接对象
String url = "jdbc:mysql://localhost:3306/haogu?serverTimezone=Asia/Shanghai";
Connection connection = DriverManager.getConnection(url, "root", "123456");
//Connection ==> 网络编程的Socket
String sql = "delete from t_department where did = 7";//发给服务器的sql
PreparedStatement pst = connection.prepareStatement(sql);
//PreparedStatement ==> IO流 网络编程的socket.getOutputStream()发生数据用的
int len = pst.executeUpdate();
//返回sql影响的记录数
System.out.println(len > 0 ? "删除成功" : "删除失败");
pst.close();
connection.close();
}
}
/*
mysql> select * from t_department;
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 研发部 | 负责研发工作 |
| 2 | 人事部 | 负责人事管理工作 |
| 3 | 市场部 | 负责市场推广工作 |
| 4 | 财务部 | 负责财务管理工作 |
| 5 | 后勤部 | 负责后勤保障工作 |
| 6 | 测试部 | 负责测试工作 |
+-----+--------+------------------+
6 rows in set (0.00 sec)
*/
1.3.4 查询数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/*
步骤:
1、一个项目引入一次数据库驱动jar就可以
2、建立数据库连接
(1)加载驱动类:通过Class类的forName方法注册驱动
(2)获取数据库连接
通过DriverManager类的静态方法获取数据库连接对象
3、通过数据库连接对象获取Statement或PreparedStatement对象,用来执行sql
4、通过Statement或PreparedStatement对象调用
(1)int executeUpdate():执行insert,update,delete等更新数据库数据的sql
(2)ResultSet executeQuery():执行select查询的sql,返回一个结果集
(3)boolean execute():可以用来执行DDL语句
遍历结果集ResultSet的方法:
boolean next():判断是否还有下一行
getString(字段名或序号),getInt(字段名或序号),getObject(字段名或序号)
5、关闭,释放各种资源
*/
public class TestSelect {
public static void main(String[] args)throws Exception {
//把驱动类加载到内存中
Class.