概念
英文全称:Java DataBase Connectivity ;java数据库连接,java语言操作数据库
jdbc的本质:是sun公司定义的一套操作所有厂商的数据库的规则,也可以称作为一组接口,各个数据库的厂商独自来实现自己对应的接口,即提供自己厂商的数据库驱动jar包,我们在使用这套接口编程的时候,实际上真正执行的是驱动jar包中的实现类。
类似于一下代码(体现了多态的调用):
person接口 female类
Person p=new female();
p.eat();
实操一波
代码演示过程:
步骤:
导包
注册驱动
建立连接对象
定义sql
获取sql语句的对象Statement
执行sql语句,接收返回来的结果
处理结果(下面代码中只演示了查询的功能select)
释放资源
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
//4.定义sql语句
String sql = "select *from tstudent";
// 5.获取执行sql语句的对象Statement
Statement statement = conn.createStatement();
//6.执行sql
ResultSet resultSet = statement.executeQuery(sql);
//7.处理结果
while (resultSet.next()) {
// 下面的写法 在工作中 很少用
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
Date uid = resultSet.getDate(3);
String time = resultSet.getString(4);
System.out.println("学号:" + id + ",姓名:" + name + ",生日:" + uid + ",性别:" + time);
System.out.println("-----------------------");
}
//8.释放资源
statement.close();
conn.close();
}
}
注意导入jar包的时候的操作:add as library
补充navicat中查看器执行sql语句:
在navicat中不可以使用修改****update tclass set cname = ‘自动’ where ccode = 18001;
详解各个类
1.DriverManger接口,驱动管理对象
* 功能:
1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。
写代码使用: Class.forName(“com.mysql.jdbc.Driver”);
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException(“Can’t register driver!”);
}
}
2.获取数据库连接
- 方法:static Connection getConnection(String url, String user, String password)
* 参数:
* url:指定连接的路径
* 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
* 例子:jdbc:mysql://localhost:3306/mydb
* 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
* user:用户名
* password:密码
注意:
静态语句块:随着类的加载,就加载到内存
真正注册驱动的是DriverManager
jar包版本5之后就可以省略注册驱动jar包
2. Connection接口:数据库连接对象
- 功能:
1. 获取执行sql 的对象
* Statement createStatement()
* PreparedStatement prepareStatement(String sql)
2. 管理事务:
* 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
* 提交事务:commit()
* 回滚事务:rollback()
下图解释:Statement和PrepareStatement的区别父子关系
3.Statement接口:执行sql的对象
- 执行sql
1.boolean execute(String sql) :可以执行任意的sql,返回值表示有没有执行sql成功 了解即可
2.int executeUpdate(String sql) :执行DML(insert、update、delete增删改)语句、DDL(create,alter、drop)语句
返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。 如果是DDL就不会返回结果,为了显示int,返回0表示
3.ResultSet executeQuery(String sql) :执行DQL(select查询)语句
2.代码练习crud语句- account表 添加一条记录
- account表 修改记录
- account表 删除一条记录
package com.mysql.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 增加一条记录
*/
public class JdbcDemo02 {
public static void main(String[] args) {
// 1.导入驱动包
Statement statement = null;
Connection conn = null;
try {
// 2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3. 获取数据库连接对象 Connection
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatisdb", "root", "123456");
// 4. 定义sql
String sql = "insert into account1 values(4,'李四',3000)";
// 5. 获取执行sql语句的对象 Statement
statement = conn.createStatement();
// 6. 执行sql,接受返回结果
int i = statement.executeUpdate(sql);
// 7. 处理结果
if (i > 0) {
System.out.println("添加成功");
} else {
System.out.println("添加失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
// 8. 释放资源
finally {
//判断空指针异常
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
其他两个修改、DDL语句只用修改sql语句就可以了,其他的一模一样
//修改sql语句
String sql = "UPDATE account1 set balance=1300,name='张三' where id=4";
//DDL语句
String sql = "create TABLE student(id int,NAME VARCHAR (20))";
注意:
创建资源就要释放资源,不然会造成内存泄漏,会使内存变小了。
4.ResultSet:结果集对象,封装查询结果
- 使用步骤:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
//循环判断游标是否是最后一行末尾。
while(rs.next()){
//获取数据
//6.2 获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + "---" + name + "---" +balance);
}
5.PreparedStatement:执行sql的对象
1.SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
1. 输入用户随便,输入密码:a' or 'a' = 'a
2.sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
//依然可以登录,称为注入问题
- 解决sql注入问题:使用PreparedStatement对象来解决
3.预编译的SQL:参数使用?作为占位符
定义工具类
1.获取连接对象的方法,要求:不传参,但是保证工具类的通用性
获取连接对象的数据较为麻烦,可以写到配置文件中
然后再工具类中写一个静态语句块(读取资源文件)步骤:
创建properties集合类
(获取src路径下的文件的方式->ClassLoader类加载器)
加载文件
获取数据、赋值(键值需要保持一样)
注册驱动
引入配置文件方法的缘由见下面两张图片(下面两张图片使用的是方法的传参但是这个方法没有带来便捷性反而多了一步抽取,显然不合适):
2.资源释放的方法(较为麻烦)
要求:
释放不同的对象,方法是原来的静态方法(两个参数)然后实现重载方法(三个参数)
先释放小的,在释放大的
一般需要静态方法方便调用。
3.注册驱动抽取
写到资源文件中
附上工具类的代码:
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具类
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
*/
static{
//读取资源文件,获取值。
try {
//1. 创建Properties集合类。
Properties pro = new Properties();
//获取src路径下的文件的方式--->ClassLoader 类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
// System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
//2. 加载文件
// pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties"));
pro.load(new FileReader(path));
//3. 获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4. 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(ResultSet rs,Statement stmt, Connection conn){
if( rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}