基础1(原生jdbc及其工具类的创建)
1. JDBC概述
用于操作数据库的java技术,此技术包含了很多操作数据库的接口,对象,方法,是一种标准 Java DataBase Connectivity->java数据库连接技术
2. JDBC四大核心接口
a.DriverManager 类 用户注册驱动
b.Connection 接口 用于连接数据库,获取连接
c.Statement 接口 用于执行sql语句
d.ResultSet 接口 用于处理结果集->针对于查询
2.JDBC开发步骤详解
1. 基本步骤
1.注册驱动 DriverManager类
2.获取连接 Connection接口
DriverManager类中的方法:
static Connection getConnection(数据库地址, 数据库登录用户名, 数据库登录密码)
3.获取执行平台 Statement接口->用于执行sql语句
Connection接口中的方法:
Statement createStatement()
4.执行sql Statement中的方法
Statement中的方法:针对不用的sql语句,调用不同的方法去执行
int executeUpdate(String sql) -> 针对于增删改操作
ResultSet executeQuery(String sql)->针对于查询操作,要处理结果集
5.处理结果集 ResultSet接口
a.针对于增删改操作,不用处理结果集
b.针对于查询操作,用处理结果集:其实就是遍历结果集,将结果集中的查询结果获取出来
6.关闭资源 close()方法
2. JDBC注册驱动
1. 注册驱动
a.用到的类:DriverManager
b.方法:static void registerDriver(Driver driver)->注册驱动
c.参数:Driver接口,调用registerDriver方法时需要传递Driver接口的实现类
Driver接口是:java.sql包下的接口
java.sql.Driver接口实现类在导入的jar包中:com.mysql.cj.jdbc.Driver
d.问题:如果使用DriverManager.registerDriver(new Driver());注册驱动,其实不合适
原因:通过翻阅Driver实现类的底层我们发现,里面有一个静态代码块,
在静态代码块中也写了DriverManager.registerDriver(new Driver());
如果我们用DriverManager.registerDriver(new Driver());注册驱动,那么驱动
将会注册两次,没必要
e.如何写才能保证Driver驱动只注册一次呢?
我们不写DriverManager.registerDriver了,我们直接将Driver实现类加载到内存
Driver实现类中的静态代码块自然就给我们注册驱动了
直接反射Driver类,直接就将com.mysql.cj.jdbc.Driver加载到内存了,自然也就执行
静态代码块了
Class.forName("com.mysql.cj.jdbc.Driver");
3. JDBC获取连接
1. 获取连接
1.获取连接:Connection接口
a.获取:DriverManager类中的方法:
static Connection getConnection(String url, String user, String password)
b.参数说明:
url:数据库地址 jdbc:mysql://localhost:3306/数据库名字?时区&其他参数
user:数据库登录用户名 root
password:数据库登录密码
2.注意:
a.mysql8中导入的jar包如果是mysql-connector-java-8.0.19.jar需要指定时区
serverTimezone=UTC
UTC是世界协调时间
mysql8中导入的jar包如果是mysql-connector-java-8.0.25.jar不需要指定时区
b.rewriteBatchedStatements=true 代表可以批量添加执行添加sql语句
mysql默认,不能批量执行添加语句,他会将多条sql拆散,一句一句执行
如果添加了此参数rewriteBatchedStatements=true,mysql就会批量执行添加语句
c.url中?后面写的就是参数
参数都是key=value形式,每一组参数用&连接
请求路径?参数&参数
示例:
import java.sql.*; public class JDBCTest { public static void main(String[] args) throws Exception { // 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 连接参数 String url = "jdbc:mysql://localhost:3306/day02"; String username = "root"; String password = "root"; // 获取连接 Connection conn = DriverManager.getConnection(url, username, password); // 获取sql语句的执行平台 String sql = "select * from people"; PreparedStatement pre = conn.prepareStatement(sql); // 执行sql语句 ResultSet res = pre.executeQuery(); // 遍历结果集 while (res.next()){ int id = res.getInt("id"); String name = res.getString("pname"); int age = res.getInt("age"); System.out.println(id + ":" + name + ":" + age); } } }
4. JDBC实现增删改操作
1. 注册驱动
2. 获取连接
3. 获取执行平台-> Statement接口-> 执行sql
Connection接口下的方法:Statement createStatement()
4. 执行sql:Statement接口中的方法
int executeUpdate(String sql)-> 针对于增删改操作->不用处理结果集
ResultSet executeQuery(String sql) -> 针对于查询操作,由于查询出来时有很多数据,所以需要容器存放,所以返回结果集
5. 关闭资源
5. JDBC实现查询操作
1. 执行查询语句的方法:
ResultSet executeQuery(String sql) -> 针对于查询操作,由于查询出来时有很多数据,所以需要容器存放,所以返回结果集
2. 处理结果集:从ResultSet中获取查询的数据->查询出来的数据会先封到ResultSet中,我们需要从ResultSet中获取查询的数据
3. 获取结果集中的数据
int getInt(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
int getInt(String columnLabel) -> 获取指定列的数据
columnLabel:写的是列名
String getString(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
String getString(String columnLabel) -> 获取指定列的数据
columnLabel:写的是列名
Object getObject(int columnIndex)->获取第几列的数据
columnIndex:写的是第几列
Object getObject(String columnLabel)-> 获取指定列的数据
columnLabel:写的是列名
3.PrepareStatement预处理对象
1. sql注入的问题
问题描述: 再进行账号密码登录验证时, 用户输入的信息,如果通过拼接的形式拼接到sql语句 中,如果密码输入:345' or '1' = '1 ,其中的单引号会对原sql语句进行重新分割,就会登录成功
2. 使用预处理对象(PreparedStatement)实现操作
1.概述:PreparedStatement 是一个接口 是Statement接口的子接口
2.获取:使用Connection接口中的方法:
PreparedStatement prepareStatement(String sql) -> 获取PreparedStatement对象,传递sql语句
3.特点:
在执行sql的时候,sql语句支持使用占位符-> ?
String sql = "select * from username = ? and password = ?";
后面再对每一个?赋值
4.为占位符赋值:
void setObject(int parameterIndex, Object x)
parameterIndex:写的是第几个?
x:代表为?赋的值
5.执行sql:PreparedStatement中的方法
int executeUpdate()
ResultSet executeQuery()
3. mysql批量添加数据
1.在设置完所有要添加的参数,调用PreparedStatement中的addBatch(),将SQL语句添加到 PreparedStatement中
2.调用PreparedStatement中的executeBatch()方法批处理sql语句
4.结合Properties文件创建JDBC工具类
1. 思路: 从JDBC的使用特点出发,可以得到使用JDBC连接数据库驱动的注册和连接的获取都是固定的模式,所以可以先抽取注册驱动和获取连接的功能,为保证器加载优先级和只需加载一次的特性放在静态代码块中进行操作, 这时会发现其中获取连接是用到的url,username,password被写死的话,如果用于连接的数据库库名和密码修改后,再想连接数据库就需要改源码,因此为解决这一问题可以使用properties文件进行连接信息的输入.
2. 配置在properties文件中的获取数据库的连接信息,可以通过Properties进行获取到工具类中进行使用,再次修改连接信息时只需要修改properties中的文件信息即可
jdbc工具类代码:
public class JDBCUtils2 {
private static String url;
private static String name;
private static String password;
/*
由于注册驱动和初始化url username password参数
应该最先执行,而且只执行一次即可
所以我们应该把这些代码放到静态代码块中
*/
static {
//注册驱动
try {
//创建Properties集合
Properties properties = new Properties();
//读取配置文件
InputStream in = JDBCUtils2.class.getClassLoader().getResourceAsStream("jdbc.properties");
//调用load方法,将流中的数据加载到集合中
properties.load(in);
//获取Properties集合职工的数据
String driver = properties.getProperty("driver");
Class.forName(driver);
url = properties.getProperty("url");
name = properties.getProperty("username");
password = properties.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConn() {
Connection connection = null;
try {
connection = DriverManager.getConnection(url, name, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 关闭资源
*/
public static void close(Connection connection, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}