推荐阅读:Druid 数据库连接池详解
文章目录
快速入门
Java操作数据库的流程
1.编写Java代码;
2.Java代码将SQL发送到MySQL服务端;
3.MySQL服务端接收到SQL语句并执行该SQL语句;
4.将SQL语句执行的结果返回给Java代码;
JDBC具体实现流程
1.创建工程,导入驱动jar包;
2.注册驱动:Class.forName("com.mysql.jdbc.Driver");
3.获取连接: Connection conn = DriverManager.getConnection(url, username, password);
Java代码需要发送SQL给MySQL服务端,就需要先建立连接;
4.定义SQL语句:String sql = “update…” ;
;
5.获取执行SQL对象:执行SQL语句需要SQL执行对象,而这个执行对象就是Statement对象,Statement stmt = conn.createStatement()
;
6.执行SQL:stmt.executeUpdate(sql);
7.处理返回结果;
8.释放资源;
API详解
DriverManager 获取连接
注册驱动
DriverManager(驱动管理类)作用:注册驱动;
在Java文档中static void registerDriver(Driver driver)
方法是用来注册驱动的。
查询MySQL提供的Driver类,可以看到该方法是在静态代码块中实现的。代码如下:
在该类中的静态代码块中已经执行了 DriverManager
对象的registerDriver()
方法进行驱动的注册了,那么我们只需要加载 Driver
类,该静态代码块就会执行。而Class.forName("com.mysql.jdbc.Driver");
就可以加载Driver 类。
因此连接数据库前,我们只需执行以下代码即可。
Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.cj.jdbc.Driver"); #JDBC 6版本及以后使用
注意
MySQL 5之后的驱动包,可以省略注册驱动的步骤,其会自动加载jar包中META-INF/services/java.sql.Driver
文件中的驱动类。
获取数据库连接
static Connection getConnection(String url, String user, String password)
参数说明
url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
示例:jdbc:mysql://127.0.0.1:3306/db1
* 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
* 配置 useSSL=false 参数,禁用安全连接方式,解决警告提示
user:用户名
poassword :密码
代码示例
public class connect {
public static void main(String[] args) throws Exception {
// MySQL 5之后的驱动包,可以省略注册驱动的步骤
// Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://127.0.0.1:3306/sd?useSSL=false";
String user="root";
String password="root";
try {
Connection conn= DriverManager.getConnection(url,user,password);
System.out.println("连接成功!");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Connection 获取对象
获取执行 SQL 的对象
1.普通执行SQL对象
Statement createStatement()
2.预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
该方法是常用方法,可以防止SQL注入,会在本文后面详细讲解 。
3.执行存储过程的对象
CallableStatement prepareCall(sql)
通过这种方式获取的 CallableStatement
执行对象是用来执行存储过程的,但存储过程在MySQL中不常用。
代码示例
public class connect {
public static void main(String[] args) throws Exception {
// MySQL 5之后的驱动包,可以省略注册驱动的步骤,
// 因为会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
// Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/sd?useSSL=false&serverTimezone=UTC+8&useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
String sql="update course set cname='C++' where cno=1";
Statement stmt=conn.createStatement();
int count=stmt.executeUpdate(sql);
System.out.println(count);
}
}
事务管理
开启事务: BEGIN; 或者 START TRANSACTION;
提交事务: COMMIT;
回滚事务:ROLLBACK;
MySQL默认是自动提交事务
开启事务
void setAutoCommit(boolean autoCommit)
参与autoCommit 表示是否自动提交事务,true表示自动提交事务,false表示手动提交事务。而开启事务需要将该参数设为false。
提交事务
void commit()
回滚事务
void rollback()
代码示例
public class connect {
public static void main(String[] args) throws Exception {
// MySQL 5之后的驱动包,可以省略注册驱动的步骤
// Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/sd?useSSL=false";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
String sql1="update course set cname='Java' where cno=1";
String sql2="update course set cname='Java' where cno=2";
Statement stmt=conn.createStatement();
try {
int count1=stmt.executeUpdate(sql1);
System.out.println(count1);
int i=1/0; // 人为制造异常,以观察归滚操作
int count2=stmt.executeUpdate(sql2);
System.out.println(count2);
//若没有异常 ,则提交所有改动,数据库更新
conn.commit();
} catch (SQLException e) {
//若存在异常,则撤销此前的所有操作(sql1的更新操作)
conn.rollback();
}
}
}
Statement 执行语句
Statement对象的作用就是用来执行SQL语句。而针对不同类型的
SQL语句使用的方法也不一样。
执行DDL、DML语句:executeUpdate
int executeUpdate(String sql)
执行DQL语句:executeQuery
ResultSet executeQuery(String sql)
该方法涉及到了 ResultSet 对象,会在本文后面详细讲解。
代码示例
public class connect {
public static void main(String[] args) throws Exception {
// MySQL 5之后的驱动包,可以省略注册驱动的步骤
// Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/sd?useSSL=false";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
String sql1 = "update st set age=15 where name='Tom'";
String sql2 = "select * from st";
Statement stmt = conn.createStatement();
//执行DDL、DML语句
int c = stmt.executeUpdate(sql1);
System.out.println(c);
System.out.println("------------------");
//执行DQL语句:查询
ResultSet rs = stmt.executeQuery(sql2);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + " " + name + " " + age);
}
}
}
运行结果
ResultSet 处理返回结果
概述
ResultSet
封装了SQL查询语句的结果,执行了DQL语句后就会返回该对象。
ResultSet executeQuery(String sql)
ResultSet
对象提供了操作查询结果数据的方法,如下:
方法 | 说明 |
---|---|
boolean next() | 将光标下移一行后并判断新的行是否有效,true 有效、false 无效 |
获取数据
Xxx getXxx(参数);
Xxx
:要查询的数据类型,如getInt(参数)
;
参数
:
用列的名称查询的话是传String
类型,如getString("name");
用列的索引查询的话,传int
类型,表的第一列索引为1,如getString(1);
代码示例
public class connect {
public static void main(String[] args) throws Exception {
// MySQL 5之后的驱动包,可以省略注册驱动的步骤
// Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/sd?useSSL=false";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
String sql = "select * from st";
Statement stmt = conn.createStatement();
System.out.println("---------用列的名称查询----------");
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + " " + name + " " + age);
}
System.out.println("---------用列的索引查询----------");
ResultSet rs1 = stmt.executeQuery(sql);
while (rs1.next()) {
int id = rs1.getInt(1);
String name = rs1.getString(2);
int age = rs1.getInt(3);
System.out.println(id + " " + name + " " + age);
}
}
}
PreparedStatement 防注入
PreparedStatement作用:预编译SQL语句并执行,预防SQL注入问题。它是通过将特殊字符进行转义实现的。
获取 PreparedStatement 对象
PreparedStatement prepareStatement(String sql)
// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"user");
pstmt.setInt(2,123456);
设置参数值
PreparedStatement对象:setXxx(参数,值):给 ? 赋值
Xxx:数据类型 ; 如 setInt(1,10);
参数: ?
的位置编号,从1开始;
**值:**给参数所赋的值
执行SQL语句
调用executeUpdate() 和 executeQuery()
这两个方法时不需要再传递SQL语句,因为获取SQL语句执行对象时已经对SQL语句进行预编译了。
public void testPreparedStatement() throws Exception {
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "1234";
Connection conn = DriverManager.getConnection(url, username, password);
// 接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1";
// 定义sql
String sql = "select * from tb_user where username = ? and password = ?";
// 获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
// 执行sql
ResultSet rs = pstmt.executeQuery();
// 判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
}
//7. 释放资源
rs.close();
pstmt.close();
conn.close();
}