JDBC技术(前篇)
JDBC技术
1.JDBC
1.1 什么是JDBC
Java database connectivity,java连接数据库,其实就是通过java语言里按揭数据库。
原来在操作数据库是在控制台写sql语句来操作数据库,jdbc就是通过向数据库发送 sql语句操作数据库。
JDBC原理:
比如 买完电脑,装上显卡,还需要安装显卡的驱动,那么显卡驱动程序包是
显卡的厂商提供。
JDBC操作数据库:mysql、oracle、DB2等数据库,前提是导入数据库驱动的程序包。
那么这些数据库驱动的程序包是谁提供的?数据库厂商提供。
程序员通过操作JDBC这一组接口就可以操作不同的数据库了。
1.2 JDBC常用的API
1.Driver(接口):在java.sql包下面.里面常用的方法是可以获取数据库驱动程序的版本号。
2.DriverManager(类):在java.sql包下面,获取数据库连接对象,注册驱动。
[1]注册数据库驱动:registerDriver(Driver driver)
[2]获取数据库连接,Connection con=getConnection(url,username,password);
url:与数据库连接的地址
username:安装数据库时的用户名
password:数据库的密码
3.Connection接口:在java.sql包下面,获取发送sql语句的对象
[1].Statement st=createStatement();
[2].PreparedStatement pst=prepareStatement(sql语句);
4.Statement接口:在java.sql包下面,向数据库发送sql语句,操作数据库。
[1].对数据库进行添加、删除、修改或者在数据库里面创建表等操作,一句话就是
对数据库进行DML(insert into,update,delete)、DDL(create,drop)操作
int row=executeUpdate();
[2].对数据库进行查询操作。
ResultSet rs=executeQuery(String sql);
5.PreparedStatement接口:在java.sql包下面,是Statement的子接口。
[1].对数据库进行添加、删除、修改或者在数据库里面创建表等操作,一句话就是
对数据库进行DML(insert into,update,delete)、DDL(create,drop)操作
int row=executeUpdate();
[2].对数据库进行查询操作。
ResultSet rs=executeQuery();
6.ResultSet接口:在java.sql包下面,用来封装查询的结果。
[1].获取查询的结果
比如获取字段类型为varchar的值:getString(字段的名称或者字段索引);
获取字段类型为int的值:getInt(字段名或字段索引);
结论:获取字段对应的值:getXXX(字段名称/字段索引);//XXX为具体类型
1.3 实现第一个JDBC案例
--------简单查询案例链接 (点我)
通过java代码操作数据库的具体步骤:(前提是导入数据库驱动的jar包)
1.注册并加载驱动:DriverManager.registerDriver(Driver driver);
或者Class.forName(“driverName”);
2.获取Connection连接对象
Connection con=DriverManager.getConnection(url,username,password);
3.获取操作数据据库的对象Statement(或者PreparedStatement)
Statement stmt=con.CreateStatement();
4.向数据库发送sql语句,执行操作。
比如执行查询操作:String sql=“select * from users”;
调用executeQuery(sql);
5.执行查询操作,返回ResultSet结果集对象,结果集里面封装了查询的结果。
遍历ResultSet,获取我们查询的数据。
6.关闭连接,释放资源(倒关原则:先创建的后关)
准备工作:
1.创建数据库:jdbc,在这个数据库里创建表,插入几条数据。
//创建数据库
create database jdbc;
use jdbc;
//创建表
create table users(id int primary key auto_increment,
name varchar(32),
password varchar(32),
email varchar(160),
birthday Date
);
//插入的sql语句
Insert into users(name,password,email,birthday) values('zzs','123','zzs@qq.com','1990-09-09');
Insert into users(name,password,email,birthday) values('lss','123','lss@qq.com','1990-09-09');
Insert into users(name,password,email,birthday) values('tianqi','123','tianqi@qq.com','1990-09-09');
注意
:1.在开发中通常使用Class.forName(“com.mysql.cj.jdbc.Driver”);注册驱动//jdk8以上用这个名字
不用DriverManger的注册驱动方法,因为这个方法注册了两次驱动(可查看java源码发现)
2.关闭资源时,关闭资源的代码一定要放在finally代码块里面,因为前面的代码无论是否发生异常,
这个块里的关闭资源代码总会被执行。因为数据库连接资源很宝贵,数据库连接资源是有限的,所以
一定要关。
1.4 PreparedStatement对象
PreparedStatement和Statement区别:
[1]功能:都可以向书库发送sql语句,对数据库进行增删改查操作。
[2]Statement操作数据库时,如果执行相同的sql语句多次,每次都会对sql语句进行编译,效率太低。
prepareStatement操作数据库时,会提前预编译,所以多次执行的sql语句,效率会提高很多。
java.sql.Date和java.util.Date之间的关系
----向数据库中插入一条语句(链接)
注意:数据库插入日期值,一定要用java.sql.Date.
[1].java.sql.Date是子类,java.util.Date时父类
[2].两个Date之间的相互转换
java.util.Date utilDate=new java.sql.Date();
java.sql.Date sqlDate=new java.sql.Date(new java.util.Date().getTime());
1.5 ResultSet对象
结果集对象是用来封装查询出来的数据(查询出来的数据其实就是一张表)
调用next方法跳转到下一行,逐个获取这一行的所有数据
如果想支持结果集的滚动效果,在创建Statement对象时,就得支持滚动效果。
----演示滚动结果集(链接)
简单查询
package cn.itcast.jdbc.esample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import com.mysql.cj.jdbc.Driver;
public class Example01 {
// 执行查询操作
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 1.注册并加载驱动
// Driver driver=new Driver();
// DriverManager.registerDriver(driver);//通过查看java源码发现这里注册了两次,这种用的不多
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql://localhost:3306/jdbc?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT";
String user = "root";
String password = "123456";
con = DriverManager.getConnection(url, user, password);
// 3.获取操作数据的对象
stmt = con.createStatement();
// 4.向数据库发送查询语句
String sql = "select * from users";
rs = stmt.executeQuery(sql);
// 5.遍历结果集,获取查询的数据
while (rs.next()) {// 跳转到下一行,在某一行的值遍历完毕后才会跳转到下一行去遍历
int id = rs.getInt(1);// 参数用名称或者索引都可以
String name = rs.getString("name");
String psw = rs.getString(3);
String email = rs.getString("email");
Date birthday = rs.getDate("birthday");
System.out.println(id + " " + name + " " + psw + " " + email + " " + birthday);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭连接,释放资源(下面为更健壮的写法,若直接关可能回报空指针异常)
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
向数据据库插入一条数据
package cn.itcast.jdbc.esample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
/*
* 向数据库插入一条数据
*
*/
public class Example02 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pst=null;
try {
//1.注册和加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT";
String user = "root";
String password = "123456";
con=DriverManager.getConnection(url, user, password);
//3.获取执行sql语句的对象
String sql="insert into users values(?,?,?,?,?)";//占位符--?
pst=con.prepareStatement(sql);
//4.执行sql前,要给占位符赋值
pst.setInt(1,100);
pst.setString(2,"欧阳菲凡");
pst.setString(3, "1232312321");
pst.setString(4, "qq.com");
java.sql.Date date=new java.sql.Date(new Date().getTime());
pst.setDate(5,date);//数据库里面的日期类型对应的时java.sql.Date
int row=pst.executeUpdate();
if(row==1){
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
} catch (Exception e) {
e.printStackTrace();
}finally {//释放资源,倒着关
if(pst!=null){
try {
pst.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pst=null;//快速释放
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
从运行结果可看出确实增加了一条数据
演示滚动结果集
package cn.itcast.jdbc.esample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 演示滚动结果集(这个简单了解即可)
*/
public class Example03 {
public static void main(String[] args) {
Connection con=null;
Statement stmt=null;
ResultSet rs=null;
try{
//1.注册和加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT";
String user = "root";
String password = "123456";
con=DriverManager.getConnection(url, user, password);
//3.获取执行sql语句的对象,支持滚动结果集
stmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
//4.执行sql语句
rs=stmt.executeQuery("select * from users");
//5.遍历结果集
//演示直接获取第二行的数据
rs.absolute(2);//光标(游标)定位到第二行
System.out.println("获取第二行的name值: "+rs.getString("name"));
//获取第一行值
rs.beforeFirst();//把光标定位在第一行的前面
rs.next();//把光标定位到第一行
System.out.println("获取第一行的name值: "+rs.getString("name"));
//演示获取最后一行的值
rs.afterLast();//把光标放在最后一行的后面
rs.previous();//把光标移动到最后一行的上面
System.out.println("获取最后一行的name值: "+rs.getString("name"));
}catch(Exception e){
e.printStackTrace();
}finally{//释放资源,倒着关(先创建的后关闭)
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?