JDBC
概念
JDBC (Java DataBase Connectivity) java数据库连接
即java语言操作数据库,本质是一套操作所有关系型数据的规则(接口),数据厂商去实现接口,提供数据库驱动jar包。真正执行的是驱动jar包中的实现类
好处:程序员只需调用JDBC接口中的方法去访问数据库程序,不用关注类如何实现,同一套代码,可以支持其他数据库
基本步骤流程
1.导入驱动jar包
2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
3.获取数据库连接对象Connection
Connection conn = DriverManager.getConnection("jdbc:mysql:///服务器名或 IP 地址:端口号/数据库","账号","密码");
4.定义sql
5.获取执行sql语句对象Statement
6.执行sql,接收返回结果集
7.处理结果
8.释放资源
JDBC核心API
接口或类 | 作用 |
---|---|
DriverManager类 | 注册数据库驱动,得到数据库连接对象 |
Connection接口 | 数据库连接对象 |
Statement接口 | 执行sql的对象 |
ResultSet接口 | 结果集对象,封装查询结果 |
PreparedStatement接口 | 执行sql的对象,是 Statement 的子接口 |
DriverManager
驱动管理对象
作用:
1.管理和注册驱动
2.创建数据库连接
1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
:在mysql5之后的驱动jar包可以省略注册驱动的步骤。,因为查看源码在com.mysql.jdbc.Drive
r类中存在静态代码块
2.获取数据库连接
方法
-
static Connection getConnection(String url, String user, String password)
:通过连接字符串,用户名,密码来得到数据 库的连接对象 -
static Connection getConnection (String url, Properties info)
:通过连接字符串,属性对象来得到连接对象
参数:
url:指定连接的路径
user:用户名
password:密码
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例如//jdbc:mysql://localhost:3306/stu
//如果连接的是本机mysql服务器,mysql默认端口号也是3306,则可以简写为 jdbc:mysql:///数据库名称
如果出现乱码问题,可以指定字符串 :
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
使用mysql8,还可能会出现时区问题,解决:
jdbc:mysql://localhost:3306/数据库?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true
Connecton接口
数据库连接对象,具体的实现类由数据库的厂商实现
方法:
Statement createStatement()
:创建一条 SQL 语句对象
功能:
1.获取执行SQL的对象
Statement createStatement()
PreparedStatement prepareStatement(String sql)
2.管理事务
开启事务: setAutoCommit(boolean autoCommit):调用方法设置参数为false,开启事务
提交事务: commit():
当所有sql都执行完提交事务
回滚事务:rollback(): 在catch中回滚事务
Statement接口
代表一条语句对象,返回结果集
方法:
-
int executeUpdate(String sql)
:用于发送 DML 语句,增删改的操作,insert、update、delete 参数:SQL 语句 返回值:返回对数据库影响的行数,返回值>0的则执行成功。 -
ResultSet executeQuery(String sql)
:用于发送 DQL 语句,执行查询的操作。select 参数:SQL 语句 返回值:查询的结果集 -
boolean execute(String sql)
:可以执行任意的sql
ResultSet接口
结果集对象,封装查询结果,对结果集进行遍历,取出每一条记录
方法:
-
boolean next()
:游标向下移动一行,判断当前行是否最后一行,是返回false,不是返回true -
数据类型 getXxx()
:获取数据
Xxx:代表数据类型 如: int getInt() , String getString()
参数:
int ,代表列的编号 从1开始 //getString(1)
String , 代表列名称 //getDouble("score")
使用步骤:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
注意事项
1.如果光标在第一行之前,使用rs.getXx获取列值。报错:Before start of result set
2.如果光标在最后一行之后,使用 rs.getXX()获取列值。报错:After end of result set
3.使用完,释放资源顺序 ResultSet----> Statement ------>Connection
PreparedStatement接口
执行SQL的对象,Statement接口的子接口,它是一个预编译(动态)的SQL语句
优点:
1.有预先编译的功能,提高 SQL 的执行效率。
1.prepareStatement()会先将 SQL 语句发送给数据库预编译。2.PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,从而提高效率。
2.可以有效的防止 SQL 注入的问题,安全性更高。
SQL注入问题
在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题,使用PreparedStatement可以防止
使用PreparedStatement步骤:
1.编写SQL语句,未知内容使用 ? 占位
select * from user where username = ? and password = ?;
2.获得PreparedStatement对象
PreparedStatement Connection.prepareStatement(String sql)
3.设置实际参数,给?赋值: setXxx(参数1,参数2)
参数1:占位符的位置 //?的位置编号 从1 开始
参数2:真实的值 // ?的值
4.执行SQL语句
5.关闭资源
思考:由于对preparedStatement为什么可以防止SQL注入抱有疑问,查阅资料后,我可以得出几点原因
1.PreparedStatement使用了预编译机制
2.PreparedStatement参数不是简单拼接生成sql,而是先用?占位,之后再根据参数产生sql
通过查看了文章[https://blog.csdn.net/u011649691/article/details/83054651]该博主的文章,最重要的原因应该是:
PreparedStatement不是将参数简单拼凑成sql,而是做了一些预处理,将参数转换为string,两端加单引号,将参数内的一些特殊字符(换行,斜杠等)进行转义处理,很大限度上避免了SQL注入