基础操作
JDBC(Java Data Base Connectivity,java数据库连接),是一种用于执行SQL语句的Java API
JDBC是接口,而JDBC驱动才是接口的实现,没有驱动无法完成数据库连接!每个数据库厂商都有自己的驱动,用来连接自己公司的数据库
使用JDBC
可以直接jar包导入,也可以使用XML快速导入(Maven)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
核心类
DriverManger(驱动管理器)
// 通过这个获取Connection连接
public static Connection getConnection() {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 三大属性
String url = "jdbc:mysql://localhost:3306/数据库名";
String name = "SQL用户名";
String pass = "SQL密码";
// 获取链接对象
return DriverManager.getConnection(url, name, pass);
}
四大参数:数据库驱动 、数据库连接地址、用户名、密码
注册驱动原理
注册驱动:Class.forName("com.mysql.jdbc.Driver")
Class.forName("")
这段代码是反射,会初始化里面的类,而 com.mysql.jdbc.Driver
类里面有以下内容
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
}
使用反射会初始化这个类里面的代码,这里面只有一个无参构造和一个静态代码块
所以使用 Class.forName("")
真正的目的就是初始化这个里面的静态代码块
也就是初始化 java.sql.DriverManager.registerDriver(new Driver())
内容
Connection(连接对象)
// 通过 Connection 里面的 Statement 对数据库进行连接然后进行操作
Statement stmt = con.createStatement();
Statement / PreparedStatement(执行对象)
public void toStatement() {
// 获取链接
Connection con = ...;
Statement statement = con.createStatement();
// sql语句
String sql = "SQL语句";
// 执行sql语句并输出结果
System.out.println("受影响的行数:" + statement.executeUpdate(sql));
// 关闭连接
statement.close();
con.close();
}
上面这种方法不是很安全,容易被SQL注入,所以有了一个新的 Statement
方法:PreparedStatement
PreparedStatement
有三个好处
- prepareStatement使用预编译sql,减少SQL编译次数,提高效率。
- 安全性更高,没有SQL注入的隐患。
- 提高了程序的可读性
public void toPreparedStatement(){
// 获取链接
Connection con = ...;
//添加预编译
PreparedStatement preparedStatement = con.prepareStatement("insert into user values (?,?)");
// 添加预编译数据
preparedStatement.setString(1, "李四");
preparedStatement.setInt(2, 123456);
// 执行sql
System.out.println("受影响的行" + preparedStatement.executeUpdate());
// 关闭连接
preparedStatement.close();
con.close();
}
可以在里面先进行SQL预编译,需要进行填写的数据可以使用 ?
来代替,下面则可以使用 .set···
方法进行数据的填入,格式为 (int,object)
,int
是第几个问号(从1开始),后面则是要填入的数据
ResultSet(查询结果集对象)
查询结果集对象是在使用SQL进行查询数据的时候,数据返回时用于接收使用,有两个非常长用的方法
一个是 next()
方法,使“行光标”移动到下一行,并返回移动后的行是否存在
一个是 getString("字段名")
方法,获取相对应的结果的列
两个配合循环输出返回的值
// 接受到结果集
ResultSet resultSet = statement.executeQuery(sql);
// 解析并输出查询结果
while (resultSet.next()) {
String name1 = resultSet.getString("name");
String pass1 = resultSet.getString("pass");
System.out.println(name1 + " - " + pass1);
}
四大参数
如果把四大参数都写在代码里面如果需要修改参数还要从新编译,解决办法就是书写一个配置文件(xml、properties...)
使用 properties 创建一个配置文件,创建一个名为 dbconfig.properties
的配置文件,然后里面写入以下内容
# 数据库驱动
driverClassName=com.mysql.jdbc.Driver
# 数据库连接地址
url=jdbc:mysql://localhost:3306/数据库名
# 数据库账号
username=xxxx
# 数据库密码
password=xxxx
一般来说名称最好是上面的,一些连接池的默认名称就是上面的,所以可以免去一些更改操作
工具类(JdbcUtils)
上述操作的代码复用性很差,每次数据操作都需要重新走一遍流程,尤其是连接非常耗费时间,所以要提高数据的复用性
分析
- 该工具类作用,就是将通用代码封装,提升代码复用性
- 通用代码包含:读取配置文件、注册驱动、获取连接对象和释放资源
- 读取配置文件、注册驱动仅需要执行一次即可,所以可以放在
JdbcUtils
工具类静态代码块完成 - 将获取连接对象和释放资源定义成静态方法,方便调用
实操
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private static String driverClassName;
private static String url;
private static String userName;
private static String password;
// 加载JDBC配置文件
static {
try {
InputStream resourceAsStream = JdbcUtils.class.getResourceAsStream("dbconfig.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
driverClassName = properties.getProperty("driverClassName");
url = properties.getProperty("url");
userName = properties.getProperty("userName");
password = properties.getProperty("password");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 注册驱动
static {
try {
Class.forName("driverClassName");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
// 获取连接资源
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, userName, password);
}
// 释放资源
public static void close(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
if (resultSet != null)
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (preparedStatement != null)
try {
preparedStatement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (connection != null)
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 释放资源
public static void close(ResultSet resultSet, Connection connection) {
close(resultSet, null, connection);
}
}