概述
- 概念:JDBC(Java DataBase Connectivity),可操作关系型数据库的接口(eg.MySQL、Oracle、DB2…)【通用接口,SQL都行】
- 作用:驱动关系型数据库,为访问不同数据库提供了同一路径
体系结构
-
接口包括两个层面
- 面向应用的API,供程序员使用
- 面向数据库的API,供数据库厂商开发程序驱动
-
Java Application —— JDBC API —— JDBC Driver Manager —— JDBC 驱动 —— 数据库
-
JDBC API
- Java官方提供
- 作用:供开发者调用的接口
- java.sql 和 javax.sql
- DriverManager 类
- Connection 接口
- Statement 接口
- ResultSet 接口
-
Driver Manager
- Java官方提供
- 作用:管理不同JDBC驱动,以获取连接
-
JDBC 驱动
- 数据库厂商提供
- 作用:负责连接不同的数据库
使用
-
导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
-
复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
-
右键–>Add As Library
-
JDBC下载链接:https://repo1.maven.org/maven2/mysql/mysql-connector-java/
-
-
注册/加载驱动【Java程序和数据库的桥梁】——类似“基站”
- 通过反射,获取运行时类,把类加载到JVM内存中
- 建议用新版本cj包的Class.forName(“com.mysql.cj.jdbc.Driver”);
- 记得处理异常
-
获取Connection连接对象,Java程序与数据库的一次连接 ——有了“基站”,电话才能打通
- 可以使用IDEA的Database插件查看数据库
- url = “jdbc:mysql://localhost:3306/[库ID]?useUnicode=true&characterEncoding=UTF-8(处理乱码)”
- user 用户名
- password密码
-
定义SQL语句
-
获取执行SQL语句的表单对象 Statement,由Connection产生
- 先创建
- 再传值(sql)
-
执行被创建的表单的SQL语句
- 增/删/改【对数据有影响】:
statement.executeUpdate(sql);
- 查【对数据无影响】:
statement.executeQuery(sql);
- 增/删/改【对数据有影响】:
-
如需接收返回值,int reult或者创建ResultSet对象,保存Statement执行之后的查询结果
- 返回值result = 1,代表成功
-
处理结果
-
释放资源
statement.close()
connection.close()
-
代码
package com.microsoft.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCDemo1 {
public static void main(String[] args){
try {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接对象
String url = "jdbc:mysql://localhost:3306/how2java?useUnicode=true&characterEncoding=UTF-8";
Connection connection = DriverManager.getConnection(url,"root","admin");
//3.定义sql语句
//String sql = "insert into account(name,money) values('张三','666')";
String sql = "select * from account";
//4.获取执行sql语句的表单对象
Statement statement = connection.createStatement();
//5.执行sql
//int result = statement.executeUpdate(sql);
ResultSet resultSet = statement.executeQuery(sql);
//6.处理结果(为1代表成功)
//System.out.println("result = " + result);
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
Double money = resultSet.getDouble("money");
System.out.println(id+" "+name+" "+money);
}
//7.释放资源
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
PreparedStatement
-
Statement本身是个接口,PreparedStatement是它的子类,提供了SQL的占位符功能
-
使用Statement开发有两个问题
- 需要频繁拼接字符串,出错率高
- 存在SQL注入的风险
-
与Statement不同的是
- 先传值
- 再创建
- 用?代替变量的值,如果有非法注入,也会被算作整个值
String name = "张三";
String sql = "select * from account where name=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,name);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
SQL注入
- 利用某些系统没有对用户输入的信息进行充分检测,在用户输入的数据中注入非法的SQL语句,从而利用系统的SQL引擎完成恶意行为
- 举个例子(下面这个所有内容就都拿得到了,可以登录成功):
select * from account where username="张三" or "1"="1" and password="123456" or "1"="1"
常见问题
-
win系统下的mysql重启(配置后需要)
-
cmd命令下:net stop mysql,停止后再net start mysql
-
连接MySql时区错误(The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more t…)
-
原因:MySql安装默认设置为美国时区,而北京时间比美国迟8小时。
-
解决方法1:
-
在mysql安装目录下找到
my.ini
文件 -
在
[mysqld]
下方添加:default-time-zone=’+08:00’ -
重启
-
-
解决方法2:
- 在连接mysql语句的url后面添加
?useSSL=true&serverTimezone=UTC
即可解决该代码报错问题
- 在连接mysql语句的url后面添加
-
-
JDBC注册驱动为什么要用反射而不是new?
-
加载驱动有两种方式
-
第一种:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
-
会导致驱动会注册两次,过度依赖于mysql的api,脱离的mysql的开发包,程序则无法编译
-
第二种:
Class.forName("com.mysql.jdbc.Driver");
-
驱动只会加载一次,不需要依赖具体的驱动,灵活性高
-
-
我们一般都是使用第二种方式,因为使用反射创建出来的对象耦合性更低,更加通用。
-