JDBC概述
1、JDBC是什么?
Java Database Connectivity(Java语言连接数据库)
2、JDBC本质是什么?
JDBC是SUN公司写的一套接口(interface)
java.sql.*; (这个软件包下有很多接口。)
接口都有调用者和实现者。
面向接口调用和面向接口写实现类,这都属于面向接口编程。
为什么要面向接口编程?
解耦合: 降低程序的耦合度,提高程序的扩展力。
多态机制就是非常典型的面向抽象编程。(不要面向具体编程)
3、为什么SUN制定一套JDBC接口?
因为每一个数据库的底层实现原理都不一样。
Oracle数据库有他自己的实现原理。
MySQL数据库有他自己的实现原理。
....
每一个数据库都有自己的实现原理。
java程序员在连接数据库的时候,不了解各个数据库底层的实现原理,所以无法编写连接数据库的代码,
只有数据库厂商自己知道自己的数据库的底层实现原理,所以连接数据库的代码必须由数据库厂商的人来编写。
于是SUN公司制定了一套连接数据库的接口,有了这套接口,Java程序员就不需要了解数据库的底层实现原理了
Java程序员和数据库厂商都面向SUN制定的这套接口编程,java程序员就可以完成java程序连接数据库了,
Java程序员面向接口调用,数据库厂商面向接口实现,java程序员面向接口调用数据库厂商面向接口编写的实现类。
4、Java程序员和数据库厂商为什么都这么听话:都面向SUN公司制定的这套接口编程?
Java程序员为了使自己的Java程序连接数据库,因为不知道数据库的底层实现原理所以必须调用这套接口来实现Java程序和数据库的连接。
接口只有调用没有实现使无法执行的,那么数据库厂商为什么这么听话乖乖的把sun公司制定的这套接口实现了,供Java程序员调用。
因为Java程序员数量众多,数据库厂商不实现SUN规定的这套接口,那么java程序员就无法通过Java连接数据库,
数据库厂商就会流失Java程序员这么一大堆用户,损失最大的还是数据库厂商。
5、各大数据库厂商编写的实现类有个专业的名词叫做“驱动”。
例如:
MySQL驱动、Oracle驱动。
驱动:所有的数据库驱动,都是以jar包的形式存在,jar包当中由很多“.class”文件,这些class文件就是对JDBC接口的实现。
驱动不是SUN公司提供的,使各大数据库厂家负责提供,下载驱动jar包需要去“数据库官网”下载。
6、模拟JDBC本质
首先充当SUN角色定义一套接口:JDBC
充当MySQL数据库厂商角色:编写JDBC的实现类MySQL,这个实现类又叫做MySQL驱动
充当Oracle数据库厂商角色:编写JDBC的实现类Oracle,这个实现类又叫做Oracle驱动
....【一堆数据库驱动】
最后就是充当程序员的角色:面向JDBC接口进行调用。程序员不用关心底层使MySQL还是Oracle。
7、怎么理解“程序员只需要面向接口进行调用就好,程序员不用关心底层使MySQL还是Oracle还是某个数据库”?
程序员只需要面向接口进行编程就好,调用方法也是接口/规范中定义的,只要学会了这套接口/规范不管底层使什么数据库,只要面向这套接口进行调用就好(但是在底层实例化数据库对象的时候还是需要我们指定将要连接的数据库是哪个品牌的数据库的,这步叫做注册驱动)。
虽然程序员不需要关心底层是什么样的数据库(不管是什么样的数据库都是调用相同的方法),但是在进行实例化的时候,还是需要指明连接的是那个数据库。
只是在连接完数据库之后,调用的方法都是一样的(与连接的是哪个数据库无关),操作也都是一样的(与连接的是哪个数据库无关),“与连接的是哪个数据库无关”这种现象叫做“程序员不需要关心底层是那个数据库”。
如果没有这套接口,MySQL有MySQL的一套规范,Oracle有Oracle的一套规则,这样程序员就需要面向具体编程,需要关心连接的这个数据库到底是MySQL的就调用MySQL规范中的方法,还是Oracle的就需要调用Oracle规范中的方法。
8、JDBC开发前准备工作,先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
使用idea开发的话不需要配置这个环境变量,idea有自己的配置方式。
classLoder从哪里加载类?
从系统的classpath环境变量中加载。所以“classpath”中一定要有一个当前路径“./”
JDBC编程六步
1、注册驱动
告诉Java程序即将要连接的是哪个品牌的数据库。
2、获取连接
JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭。
3、获取数据库操作对象
专门执行SQL语句的对象
4、执行SQL语句
主要执行DQL和DML。
5、处理查询结果集
只有当第四步执行的是select语句的时候,才有第五步处理查询结果集。
6、释放资源
使用完资源之后一定要关闭资源。jvm和dbms属于进程之间的通信,开启之后一定要关闭。
编程
1、DriverManager是Java的驱动管理器类。
不管是MySQL的驱动也好,还是Oracle的驱动也好,还是其他的驱动...
需要使用到这个驱动的时候,就需要通过Java的驱动管理器类,调用java.sql包下的
static void registerDriver(Driver driver),注册一下驱动。
2、当调用DriverManager(驱动管理器)的getConnection方法时,DriverManager将尝试从初始化中加载的驱动程序中找到合适的驱动程序,
Statement createStatement(),创建一个Statement对象,用于将SQL语句发送到数据库(dbms)。
然后调用Statement对象的executeUpdete(String sql)、executeQuery(String sql)执行SQL语句,将sql语句发送到dbms并执sql语句
3、 什么是通信协议,有什么用?
通信协议是通信之前就提前定好的数据传送格式。
数据包具体怎么传送数据,格式提前定好的。
4、url是统一资源定位符,网络中某个资源的绝对路径
url主要包括:通信协议、ip地址、port端口号、资源名
5、常用方法
【DriverManager类的方法】
static void registerDriver(java.sql.Driver driver);//注册给定的驱动程序
static Connection getConnection(String url, String user, String password) ;//尝试与给定的url的数据库建立连接
【Connection接口的方法】
Statement createStatement();//创建一个 Statement对象,用于将SQL语句发送到数据库,Statement专门用来执行SQL语句的。
PreparedStatement prepareStatement(String sql);//获取预编译的SQL语句
void setAutoCommit(boolean autoCommit);//设置自动提交,true启用自动提交模式; false禁用自动提交模式
void commit();//提交事务
void rollback();//回滚事务
【Statement接口的方法】
//返回值是影响的数据库中记录的条数
int executeUpdate(String sql);//执行给定的SQL语句,这可能是 INSERT , UPDATE ,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。
ResultSet executeQuery(String sql);//执行给定的SQL语句,查询结果自动就封装到了ResultSet对象当中了。
【所有的资源都有】
void close();//释放资源
【ResultSet接口的常用方法】
boolean next();//将光标向下移动一行,如果光标指向的这行是有效数据行,那么返回true
String getString(int columnIndex);//通过当前行的“列序号”获取某个数据,(列序号从1开始,以1递增)
String getString(String columnLabel);//通过当前行的“列名称”获取某个数据,如果有列重命名,那么小括号中跟的是,重命名的列名,不是数据表中原有的列名,是查询结果集的列名
int getInt(int columnIndex);//通过“列序号”返回某个数据
int getInt(String columnLabel);//通过“列名”返回某个数据
...其他的基本数据类型也都有getXxx()方法。
【PreparedStatement接口的常用方法】
void setString(int parameterIndex, String s);//吧s设置给sql语句中的第parameterIndex个占位符
...其他的基本数据类型也都有setXxx()方法。
ResultSet executeQuery();//执行查询语句
int executeUpdate();//执行DML语句
6、JDBC中的SQL语句不需要写分号,写生报错。
7、在反射机制中执行:Class.forName(“类”);方法的时候“类”会发生类加载动作,类的静态代码块执行。
package com.mysql.jdbc;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver()); //这行代码会完成驱动注册
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
8、Statement和PreparedStatement?
Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题。
9、使用preparedStatement的时候占位符(?)不要使用“单引号”括起来
例如:"select * from t_user where uName=? and uPwd=?"
10、当业务要求必须要使用SQL注入的时候就不能使用preparedStatement了,就必须使用Statement了。
JDBC事务
1、JDBC中的事务是自动提交的,只要执行任意一条DML语句,则自动提交一次,这是JDBC默认的事务行为,
但是在实际的业务当中,一般是n条DML语句共同联合才能完成一个功能,必须保证多条DML语句在同一个事务当中同时成功或同时失败。
2、封装工具类:
工具类的构造方法一般都是私有的。
public class JDBCUtil {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection () throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");
}
public static void close (Connection conn, Statement stmt, ResultSet rs) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
3、悲观锁和乐观锁的概念
悲观锁:事务必须排队执行。数据锁住了,不允许并发。(在select后面添加for updete)
必须等当前事务结束了,其他事务才能执行。
select查出来的相关记录就被行级锁锁住了,其他事务对相关记录就无法更改了。
乐观锁:支持并发,事务也不需要排队执行,只不过需要一个版本号。