0. 相关知识
在一个接口或类中获取下一个接口或类的对象
0.0 jar包是什么?
别人写好的一些类,然后对这些类进行了打包就形成了:jar包。你可以将这些jar包导入你的项目中,然后就可以直接使用这些jar包中的类和属性以及方法。
0.1 统一资源定位符URL
url统一资源定位符:网络中某个资源的绝对路径
例子:https://www.baidu.com/ 这就是URL。
URL包括哪几部分?
- 协议
- IP地址
- PORT
- 资源名
http://182.61.200.7:80/index.htmlhttp:// 通信协议182.61.200.7 服务器IP地址80 服务器上软件的端口号index.html 是服务器上某个资源名
------------------------------------------------------------------MySQL数据库的URL格式:jdbc:mysql://hostname:port/databaseoracle的URL格式:jdbc:oracle:thin:@localhost:1521:orcljdbc:mysql://127.0.0.1:3306/bjpowernodejdbc:mysql:// 协议127.0.0.1 IP地址3306 mysql数据库端口号bjpowernode 具体的数据库名。说明:localhost和127.0.0.1都是本机的IP地址。jdbc:mysql://192.168.151.27:3306/bjpowernode什么是通信协议,有什么用?通信协议是通信之前就提前定好的数据传送格式。数据包具体怎么传数据,格式提前定好的。
0.2 数据源
-
数据源其实是一套规范,JDK中也有这套规范,就是:javax.sql.DataSource,只要实现了javax.sql.DataSource接口的都是数据源
-
datasource数据源:为程序提供数据库连接对象Connection的都叫数据源
-
数据库连接池提供了数据库连接对象Connection,所以数据库连接池也是数据源
-
德鲁伊连接池,C3p0连接池,dbcp连接池都实现了DataSource接口
-
自己编写一个数据源
-
在数据源里面要定义连接数据库信息的4个变量,并提供这四个属性的set方法
-
package com.powernode.spring6.jdbc;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;/*** @author 动力节点* @version 1.0* @className MyDataSource* @since 1.0**/
public class MyDataSource implements DataSource {// 添加4个属性private String driver;private String url;private String username;private String password;// 提供4个setter方法public void setDriver(String driver) {this.driver = driver;}public void setUrl(String url) {this.url = url;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}// 重点写怎么获取Connection对象就行。其他方法不用管。@Overridepublic Connection getConnection() throws SQLException {try {Class.forName(driver);Connection conn = DriverManager.getConnection(url, username, password);return conn;} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}
}
1. JDBC概述
1、Java DataBase Connectivity(Java数据库连接)
JDBC是sun公司提供的一套 用于数据库操作的接口,java程序员面向这套接口编程即可。
不同的数据库厂商 对这套接口 提供了不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程
2、JDBC的本质:sun公司提供的一套 用于数据库操作的接口,然后各大数据库厂商分别实现这套接口(interface) java.sql.*; (这个软件包下有很多接口。)
MySQL驱动:其实就是MySQL厂商对JDBC的实现,用于操作MySQL数据库的
接口都有调用者和实现者。
面向接口调用、面向接口写实现类,这都属于面向接口编程。为什么要面向接口编程(面向抽象编程)?解耦合:降低程序的耦合度,提高程序的扩展能力。多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)建议:Animal a = new Cat();Animal a = new Dog();// 喂养的方法public void feed(Animal a){ // 面向父类型编程。}不建议:Dog d = new Dog();Cat c = new Cat();思考:为什么SUN制定一套JDBC接口呢?因为每一个数据库的底层实现原理都不一样。Oracle数据库有自己的原理。MySQL数据库也有自己的原理。MS SqlServer数据库也有自己的原理。....每一个数据库产品都有自己独特的实现原理。JDBC的本质到底是什么?一套接口。
2. JDBC开发前的准备工作:先从官网下载对应的jar包驱动,然后将其配置到环境变量classpath当中。
2.1 文本编辑器的方式
以下配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以下的环境变量。
classpath=.;D:\course\06-JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar
2.1 idea的配置方式
①在模块上右键,然后选择Open Modeul Settings
②然后进入到此界面,进行如下操作
然后找到要导入的jar驱动包,再选择jar包要导入哪些模块中
3. JDBC编程六步(1)
第一步:调用DriverManager接口中的registerDriver静态方法注册指定的驱动程序(或是通过反射机制注册指定的驱动程序)(作用:告诉Java程序,要连接哪个品牌的数据库)
第二步:调用DriverManager接口中的getConnection静态方法:获取数据库连接对象Connection(让java连接数据库)
第三步:通过Connection对象调用Connection接口中的方法:获取数据库操作对象Statement或preparedStatement(专门执行sql语句的对象)
第四步:通过数据库操作对象调用其中的方法执行SQL语句(DQL DML....)
第五步:(处理)打印查询结果集(只有第四步执行select语句时,才需处理查询结果集。)
第六步:关闭连接,释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
3.JDBC编程六步(2)
第一步:注册指定的JDBC驱动程序(有三种方法)
方法一:
Driver driver = new com.mysql.jdbc.Driver(); //先实例化mysql的驱动
DriverManager.registerDriver(driver); //向 DriverManager接口注册指定的JDBC驱动程序方法二:
//调用DriverManager接口中的registerDriver静态方法注册指定的JDBC驱动程序DriverManager.registerDriver(new com.mysql.jdbc.Driver());方法三:
Class.forName("com.mysql.jdbc.Driver"); //通过Java反射机制注册指定的JDBC驱动程序
第二步:调用DriverManager接口中的getConnection静态方法获取数据库连接对象Connection
String url = "jdbc:mysql://localhost:3306/bjpowernode";
String user = "root";
String pwd = "123456";
connection = DriverManager.getConnection(url,user,pwd);
第三步:通过Connection对象调用Connection接口中的方法获取数据库操作对象Statement(它专门执行sql语句的对象)
statement = connection.createStatement(); //方法一:获取用于执行静态SQL语句的数据库操作对象
preparedStatement = connection.prepareStatement(sql); //方法二:先获取预编译的数据库操作对象,sql语句已预先编译好了
第四步:通过数据库操作对象 调用 Statement接口或PreparedStatement接口中的方法:执行SQL语句(有多种方法)(如果是使用PreparedStatement对象,则需要调用设置占位符的方法给占位符设置值)
第五步:打印查询结果集(处理查询结果集,将里面的数据取出来)(只有第四步执行select语句的时候,才有这第五步处理查询结果集。)
while (resultSet.next()){String empno = resultSet.getString("empno");String enmae = resultSet.getString("ename");int salary = resultSet.getInt("sal");System.out.println(empno + "," + enmae +"," + salary);
}
第六步:关闭连接,释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
3. JDBC 编程六步(3)
//第一步:通过DriverManager接口中的 static void registerDriver(Driver driver) 静态方法注册指定的JDBC驱动程序DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //第二步:通过riverManager接口中的 static Connection getConnection(String url,String user,String pwd) 静态方法获取数据库连接对象connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");//第三步:Connection接口中的方法获取数据库操作对象statement = conn.createStatement();//第四步:调用Statement对象中的方法执行SQL语句String sql = "insert into dept(DEPTNO,DNAME,LOC) values(50,'人事部','北京')";int count = statement.executeUpdate(sql);
//第五步://第六步:释放资源:释放资源时,后开的资源先关闭if (statement != null){ //习惯:如果不为空,才关闭try {statement.close();} catch (SQLException e) {e.printStackTrace();}try {if(conn != null){conn.close();}}catch (SQLException e){e.printStackTrace();}
4、实现JDBC程序
案例1:用JDBC向数据表中添加数据
package jdbctest1;import java.sql.*;public class JDBCTest1 {public static void main(String[] args) {Statement statement = null;Connection conn = null;try {Driver driver = new com.mysql.jdbc.Driver(); //实例化mysql的驱动//oracle的驱动: Driver driver = new oracle.jdbc.driver.OracleDriver();// 1、DriverManager接口注册驱动DriverManager.registerDriver(driver); //向 DriverManager注册指定的JDBC驱动程序// 2、DriverManager接口获取数据库连接对象String url = "jdbc:mysql://127.0.0.1:3306/bjpowernode";String user = "root";String pwd = "123456";conn = DriverManager.getConnection(url,user,pwd); //获取数据库连接对象ConnectionSystem.out.println("数据库连接对象为:"+conn);// 3、Connection接口获取数据库操作对象statement = conn.createStatement();// 4、使用Statement对象执行SQL语句String sql = "insert into dept(DEPTNO,DNAME,LOC) values(50,'人事部','北京')";int count = statement.executeUpdate(sql);if (count == 1){System.out.println("修改成功");}else {System.out.println("修改失败");}} catch (SQLException e) {e.printStackTrace();}finally {//6、 释放资源:释放资源时,后开的资源先关闭if (statement != null){ //习惯:如果不为空,才关闭try {statement.close();} catch (SQLException e) {e.printStackTrace();}try {if(conn != null){conn.close();}}catch (SQLException e){e.printStackTrace();}}}}
}
案例2:用JDBC删除表中的数据行
package jdbctest1;import com.mysql.jdbc.Driver;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class JDBCTest2 { //执行DML的 delete form 表名 命令public static void main(String[] args) {Connection connection = null;Statement statement = null;try {// 1、用DriverManager接口中的registerDriver方法注册指定的JDBC驱动程序DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //向 DriverManager注册指定的JDBC驱动程序Class.forName("com.mysql.jdbc.Driver"); //通过反射机制注册数据库驱动// 2、调用DriverManager接口中的getConnection静态方法获取数据库连接对象String url = "jdbc:mysql://localhost:3306/bjpowernode";String user = "root";String pwd = "123456";connection = DriverManager.getConnection(url,user,pwd);// 3、调用Connection接口中的方法获取数据库操作对象statement = connection.createStatement();// 4、调用Statement接口中的方法执行SQL语句String sql = "delete from dept where deptno = 50";int count = statement.executeUpdate(sql);if (count == 1){System.out.println("执行成功");}else if (count == 0){System.out.println("执行失败");}}catch (SQLException e){e.printStackTrace();}finally {//6、释放资源:释放资源时,后开的资源先关闭try {if (statement != null){statement.close();}}catch (SQLException e){e.printStackTrace();}try {if (connection != null) {connection.close();}}catch(SQLException e){e.printStackTrace();}}}
}
案例3:使用java连接数据库查询数据表中的数据
package jdbctest1;import java.sql.*;public class JDBCTest3 {public static void main(String[] args) throws ClassNotFoundException {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {//1.注册数据库驱动Class.forName("com.mysql.jdbc.Driver");//2.获取数据库连接对象,表示和数据库创建了连接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");//3.获取数据库操作对象statement = connection.createStatement();//4.执行SQL语句String sql = "select * from emp";resultSet = statement.executeQuery(sql);//5.处理查询结果集while (resultSet.next()){String empno = resultSet.getString("empno");String enmae = resultSet.getString("ename");int salary = resultSet.getInt("sal");System.out.println(empno + "," + enmae +"," + salary);}}catch (SQLException e) {e.printStackTrace();}finally {//6.在finally代码块中关闭资源if (resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null){try {statement.close();}catch (Exception e){e.printStackTrace();}}if (connection != null){try {connection.close();}catch (Exception e){e.printStackTrace();}}}}
}
案例4:PreparedStatement完成增删改
5、JDBC中常用的接口及其常用方法
注册,连接,获取操作对象,执行,处理查询结果集,关闭资源
JDBC的接口主要在java.sql包中
1、Driver接口:所有JDBC驱动程序必须实现的接口,这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
MySQL的Driver接口的实现类是:com.mysql.jdbc.Driver(全类名)
2、DriverManager接口(有两个重要的静态方法):管理JDBC驱动程序的
主要方法:可以用于注册JDBC驱动程序和获取数据库连接对象Connection
DriverManager接口常用方法
方法名 | 功能 |
---|---|
static void registerDriver(Driver driver) | 注册指定的JDBC驱动程序,接收一个数据库驱动实例 |
static Connection getConnection(String url,String user,String pwd) | 获取数据库连接对象Connection,表示和数据库创建了连接(建立和数据库的连接) |
3、Connection接口:用于建立和数据库的连接,一个连接就是一个会话,建立连接后可以执行SQL语句
主要方法:建立连接后就可以获取数据库操作对象(Statement或PreparedStatement)(专门执行sql语句的对象)
Connction接口常用方法
方法名 | |
---|---|
Statement createStatement() | 获取数据库操作对象Statement(这个对象用于执行静态SQL语句),将SQL语句发送到数据库 |
PrepareStatement prepareStatement(String sql) | 将参数化的SQL语句发到数据库,获取一个预编译的数据库操作对象PrepareStatement |
4、Statement接口:执行静态的SQL语句,并返回一个结果对象。
Statement接口中的方法
方法名 | 功能 |
---|---|
boolean execute(String sql) | 能够执行所有的SQL语句,如果执行的SQL有查询结果,则返回true,否则返回false。通过getStatementSet()可以获得查询结果 |
int executeUpdate(String sql) | 用于执行 修改数据表中数据的 SQL语句(INSERT,DELETE,UPDATE),返回的int值代表受影响的行数 |
ResultSet executeQuery(String) | 执行SQL中的查询语句(如select),返回一个存储 查询结果集 的ResultSet对象 |
5、PreparedStatement接口: Statement的子接口,执行预编译的SQL语句
-
这个接口的SQL语句中的具体值可以用 ?来代替,然后通过其提供的setter()方法为 ?传值
PreparedStatement接口中的方法
方法名 | 功能 |
---|---|
int executeUpdate() | 在PreparedStatement对象中执行SQL语句,如DML、DDL,返回的int值代表受影响的行数 |
ResultSet executeQuery() | 在PreparedStatement对象中执行SQL的select语句,返回一个存储查询结果集 的ResultSet对象 |
void setInt(int parameterIndex,int x) | 将指定索引处的参数(占位符) 设置为 int类型x |
void setString(int parameterIndex,String x) | 将指定索引处的参数(占位符) 设置为 字符串类型x |
6、ResultSet接口:用来存储JDBC的查询结果集,通过结果集对象中的方法完成对数据库的访问。
(①这个查询结果集封装在一个表格中②ResultSet接口中有一个游标,当ResultSet对象初始化时游标会指向表格的第一行之前。)
Result接口常用的方法
方法名 | 功能描述 |
---|---|
String getString(int columnIndex) | 获取 游标所在行的String类型的值,根据字段的索引来获取 |
String getString(String columnName) | 获取 游标所在行的String类型的值,根据列名来获取 |
int getInt(int columnIndex) | 根据 字段索引 获取 游标所在行中int类型的值 |
int getInt(String columnName) | 根据 字段名 获取 游标所在行的int类型值 |
boolean next() | 将游标向下移动一行,从当前位置,如果没有数据了则返回false |
JDBC中的所有下标从1开始,不是从0
7、CallableStatement接口:用于执行SQL的存储过程。
数据库中特殊的数据类型:
8、Data类:标准的Date的一个子集,用于表示数据库中的日期类型,用于表示日期类型(不包含时间)
-
java.util.Date如何转化为java.sql.Date类型
-
先把日期字符串转化为java.util.Date类型
-
再把java.util.Date类型转化为java.sql.Date类型
-
9、TimeStamp类:标准的Date的一个扩展,用于表示sql中的时间戳,增加了一个关于纳秒的时间域
14、Time:标准的Date的一个子集,用于表示数据库的时间类型,用于表示时分秒(不包含其他的)
10、DatabaseMetaData:跟ResultSetMetaData一起访问数据库的元信息
11、DataTruncation:出现数据库异常时,报告异常或警告
12、SQLException:数据库异常
13、SQLWarming:数据库警告
14、DriverPrepertyInfo:驱动属性的所有信息
15、Types: 常量
6、SQL注入
-
导致SQL注入的根本原因:
-
用户输入的信息中含有sql语句的关键字,并且sql语句的关键字参与了sql语句的编译过程,导致sql语句的原意被扭曲,进而达到sql注入。
-
-
如何解决SQL注入
-
只要用户输入的信息不参与SQL语句的编译过程问题就解决了
-
要想使用户输入的信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement接口,它继承了java.sql.Statement接口
-
PreparedStatement属于预编译的数据库操作对象
-
8.Statement和PreparedStatement的对比
-
Statement的原理是:先进行SQL语句的拼接,然后再对SQL语句进行编译
-
PreparedStatement的原理是:预先对SQL语句的进行编译,然后再给SQL语句传“值”。
-
Statement和PreparedStatement的对比
-
1、Statement存在SQL注入问题,而PreparedStatement解决了SQL注入
-
2、Statement编译一次执行一次,PreparedStatement是编译一次,可执行多次(效率较高)
-
3、PreparedStatement在编译阶段做类型的安全检查
-
9.JDBC工具类封装
除了操作数据库的内容,其他都是重复的
一般工具类中的构造方法都是私有的,因为工具类中的方法都是静态的,不需要创建对象来使用,直接用类名调用即可
package utils;import java.sql.*;/*** JDBC工具类,封装JDBC代码,简化JDBC编程*/
public class DBUtil {private DBUtil(){}//注册驱动只需要注册一次就可以,所以把它放到静态代码块中//静态代码块在类加载的时候执行,且只执行一次static {try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 获取数据库连接对象* @return* @throws SQLException*/public static Connection getConnection() throws SQLException {Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bjpowernode","root","123456");return connection;}/*** 关闭数据库连接资源* @param connection 数据库连接对象* @param statement 数据库操作对象* @param resultSet 查询结果集对象*/public static void close(Connection connection, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection != null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}