创建工程,导入jar包,下载网址:https://downloads.mysql.com/archives/c-j/
注册驱动
Class.forName("com.mysql.jdbc.Driver");
获取连接
Connection conn = DriverManager.getConnection(url.username,password);
定义sql语句
String sql ="update..."
获取sql对象
Statement stmt = conn.createStatement();
执行sql
stmt.executeUPdate(sql);
处理返回结果
释放资源
代码
package com.itlyc.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* 玥骋
* JDBC 快速入门
*/
public class JBDCdemo {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "update dept set dname='李玥骋' where did=2";
//4.获取执行sql的对象statement
Statement state = conn.createStatement();
//5.执行sql
int i = state.executeUpdate(sql);//返回受影响的行数
//6.处理结果
System.out.println(i+"行受到影响");
//7.释放资源
state.close();
conn.close();
}
}
注册驱动
Driver类源码
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
//我们可以看到注册驱动的方法就在Driver类的静态方法中,随着类的加载被加载
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
获取数据库连接
static Connection getConnection(String url , String user , String password)
参数:
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?键值对1&键值对2...
例子: jdbc:mysql://127.0.0.1:3306/db01
注:如果连接的本地MySQL 并且端口号默认为3306的话可以简化书写
jdbc:mysql:///数据库名称
Connection接口中定义了三个对应的方法
例子:
package com.itlyc.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 玥骋
* JDBC API详解
*/
public class JBDCdemo_Connection {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql1 = "update dept set dname='李玥骋' where did=2";
String sql2 = "update dept set dname='肖婉茹' where did=3";
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
try {
//开启事物
conn.setAutoCommit(false);
//5.执行sql
int i1 = stmt.executeUpdate(sql1);//返回受影响的行数
//6.处理结果
System.out.println(i1+"行受到影响");
//5.执行sql
int i2= stmt.executeUpdate(sql2);//返回受影响的行数
//6.处理结果
System.out.println(i2+"行受到影响");
//提交事物
conn.commit();
} catch (SQLException e) {
//回滚事物
conn.rollback();
e.printStackTrace();
}
//7.释放资源
stmt.close();
conn.close();
}
}
package com.itlyc.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 玥骋
* JDBC API详解
*/
public class JBDCdemo_Connection {
public static void main(String[] args) throws Exception {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql1 = "update dept set dname='码云' where did=2";
String sql2 = "update dept set dname='麻花' where did=3";
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
try {
//开启事物
conn.setAutoCommit(false);
//5.执行sql
int i1 = stmt.executeUpdate(sql1);//返回受影响的行数
//6.处理结果
System.out.println(i1+"行受到影响");
//主动造一个异常,try捕获到异常,下方catch会进行处理,调用rollback()方法来回滚事务
int i = 3/0;
//5.执行sql
int i2= stmt.executeUpdate(sql2);//返回受影响的行数
//6.处理结果
System.out.println(i2+"行受到影响");
//提交事物
conn.commit();
} catch (Exception e) {
//回滚事物,
conn.rollback();
e.printStackTrace();
}
//7.释放资源
stmt.close();
conn.close();
}
}
例:
package com.itlyc.jdbc;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 玥骋
* JDBC 执行DML语句
*/
public class JBDCdemo_Statement {
@Test
public void testDML() throws Exception {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "update dept set dname='jack' where did=1";
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
//5.执行sql
int i = stmt.executeUpdate(sql);//执行完DMLsql后的返回值为受影响的行数
//6.处理结果
if (i>0){
System.out.println(i+"行受到影响,执行成功!");
}else{
System.out.println(i+"行受到影响,执行失败!");
}
//7.释放资源
stmt.close();
conn.close();
}
}
/**
* 玥骋
* JDBC 执行dml语句
*/
public class JBDCdemo_Statement {
@Test
public void testDDL() throws Exception {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "DROP database db02";//删除数据库db02
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
//5.执行sql
int i = stmt.executeUpdate(sql);//执行完DDLsql后的返回值为受影响的行数
System.out.println(i);
//7.释放资源
stmt.close();
conn.close();
}
}
ResultSet(结果集对象)作用:
封装了DQL查询语句的结果
ResultSet stmt.executeQuery(SQL):执行DQL语句返回ResultSet对象
获取查询结果
boolean next(): 1.将光标从当前位置向下移动一行
2. 判断当前行是否为有效行
返回值:
true:有效行,当前行有数据
false:无效行,当前行没有数据
xxx getXxx(参数):获取数据
1.xxx 数据类型 如:int getint(参数);String getString(参数);
2.参数
int:列的编号从1开始
String:列的名称
使用方法与步骤
1.游标向下移动一行,并判断改行是否有数据:next()
2.获取数据:getXxx(参数)
//循环判断游标是否为数据的最后一行末尾
while(rs.next){
//获取数据
rs.getXxx(参数);
}
/**
* 玥骋
* JDBC 执行DQL语句
*ResultSet的基础用法
*/
public class JBDCdemo_ResuletSet {
@Test
public void testDQL() throws Exception {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "SELECT*FROM dept";
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);//执行完DMLsql后的返回值为受影响的行数
//6.处理结果,遍历rs中的数据
while(rs.next()){
int did = rs.getInt("did");
String dname = rs.getString("dname");
System.out.println(did);
System.out.println(dname);
System.out.println("---------------------------------");
}
//7.释放资源
rs.close();
stmt.close();
conn.close();
}
}
/**
* 案例
* 查询account账户数据表,封装为Account对象中,并且存储到Arraylist集合中
* 1.定义实体类Acctount
* 2.查询数据,封装到Account对象中
* 3.将account对象存入Arraylist集合中
* @throws Exception
*/
@Test
public void testResultSet1() throws Exception {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "SELECT*FROM dept";
//4.获取执行sql的对象stmt
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);//执行完DMLsql后的返回值为受影响的行数
//new集合
ArrayList<Account> arrayList = new ArrayList<>();
//6.处理结果,遍历rs中的数据
while(rs.next()){
Account account = new Account();
//获取数据
int did = rs.getInt("did");
String dname = rs.getString("dname");
//赋值
account.setId(did);
account.setName(dname);
//存入集合
arrayList.add(account);
}
System.out.println(arrayList);
//7.释放资源
rs.close();
stmt.close();
conn.close();
}
package com.itlyc.opjo;
//Account类
public class Account {
int id;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
在获取PreparedStatment对象时,将sql语句发给mysql服务器进行检查,编译,(因为这部耗时)
执行时就不需要进行耗时的步骤,速度很快
如果sql模板一样,则只需要进行一次检查编译,大大节省时间
开启预编译
//因为预编译功能默认关闭,所以我们需要手动打开:useServerPrepStmts=true
String url = "jdbc:mysql://127.0.0.1:3306/db01?useServerPrepStmts=true";
sql日志文件
2022-03-26T06:19:26.610868Z 4 Prepare select * from dept where did=? and dname=?
2022-03-26T06:19:26.610868Z 4 Execute select * from dept where did='1' and dname='\' or \'1\'=\'1' # 注此处将敏感字符转义(' or '1'='1)
2022-03-26T06:19:26.611865Z 4 Close stmt
2022-03-26T06:19:26.611865Z 4 Quit
作用:预编译sql语句并执行,预防SQL注入问题,将敏感字符转义,并且预编译性能更高。
SQL语句已预编译并存储在preparedStatment对象中,然后,可以使用此对象多次有效的执行此语句。
/**
* 玥骋
* JDBC 用户登录小案例
*/
@Test
public void testlogin() throws Exception {
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户名和密码
String name ="2";
String pswd ="jack";
String sql = "select * from dept where did='"+name+"' and dname='"+pswd+"'";
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if (rs.next()){
System.out.println("登陆成功~");
}else{
System.out.println("登录失败~");
}
rs.close();
stmt.close();
conn.close();
}
@Test
/**
* 玥骋
* JDBC 用户登录小案例
*/
public void testlogin_Inject() throws Exception {
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户名和密码
String name ="4";
String pswd ="' or '1'='1";
String sql = "select * from dept where did='"+name+"' and dname='"+pswd+"'";
System.out.println(sql);
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if (rs.next()){
System.out.println("登陆成功~");
}else{
System.out.println("登录失败~");
}
rs.close();
stmt.close();
conn.close();
}
//我们写的sql就变成了该式子,因为and比or先执行false or true,使整个sql语句变为true,所以查询成功,登陆成功
select * from dept where did='4' and dname='' or '1'='1'
登陆成功~
为了解决sql注入问题 我们可以使用PrepareStatement
步骤:
获取PrepareStatment对象
//SQL语句中的参数值,使用?占位符替代
String sql="select * from user where username = ? and passsworld = ?";
//通过Connection 对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
设置参数值
PreparedStatement 对象:setXxx(参数1,参数2):给?赋值
注:Xxx:数据类型; 如setInt(参数1,参数2);
参数:参数1: ?的位置编号,从1开始,对应sql语句中的? 位置
参数2: ?的值,对应sql语句中的? 位置
执行sql
executeUpdate(); / executeQuery();
不在需要传递sql
防止sql注入案例:
@Test
/**
* 玥骋
* JDBC 防止sql注入小案例
*/
public void testlogin_In() throws Exception {
String url = "jdbc:mysql://127.0.0.1:3306/db01";
String username = "root";
String password = "lyc";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户名和密码
String name ="1";
String pswd ="' or '1'='1";//sql注入
String sql = "select * from dept where did=? and dname=?";//用?占位符代替我们的值
//获取pstmt对象,并把sql传入prepareStatement对象中
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置 ? 的值
pstmt.setString(1,name);
pstmt.setString(2,pswd);
//执行sql
ResultSet rs = pstmt.executeQuery();
//判断登录是否成功
if (rs.next()){
System.out.println("登陆成功~");
}else{
System.out.println("登录失败~");
}
rs.close();
pstmt.close();
conn.close();
}