JDBC-入门
一、JDBC搭建:
1.准备数据库
2.下载连接驱动jar包。
3.创建Java项目,在项目下创建lib文件夹内,将下载完成的jar包复制到文件夹里面。
4.选中lib文件夹右键–>Add as Library(添加为库),与项目集成。
5.编写代码
完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package com.Chiba.base;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCQuick {
public static <connection> void main(String[] args) throws Exception {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql://localhost:3306/jdbcdemo";
String username = "root";
//password修改成自己设置的mysql密码
String password = "password";
Connection connection = DriverManager.getConnection(url, username, password);
// 3.获取执行sql语句的对象 -->把sql语句发送给mysql的对象
Statement statement = connection.createStatement();
// 4.编写SQL语句,并执行,接受返回的结果集
String sql = "select emp_id,emp_name,emp_salary,emp_age from t_emp;";
ResultSet resultSet = statement.executeQuery(sql);
// 5.处理结果,遍历result结果集
while (resultSet.next()) {
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
double empSalary = resultSet.getDouble("emp_salary");
int empAge = resultSet.getInt("emp_age");
System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
}
// 6.释放资源(遵循先开后关原则)-->目前有connection、statement、resultSet三个资源
resultSet.close();
statement.close();
connection.close();
}
}
|
二、核心API理解
2.1注册驱动
2.2 Connection
-
Connection接口是JDBC API的重要接口,用于建立与数据库通信通道,只要Connection不为空,就代表一次与数据库连接。
-
在建立连接时,需要指定数据库URL、用户名、密码。
注:如果你用的是自己的IP地址(localhost)和默认端口号(3306)那么这时候url就可以写:com:mysql:///jdbcdemo
-
Connection接口还负责管理事务,Connection接口提供了commit和rollback方法,用于提交事务和回滚事务。
-
可以创建Statement对象,用于执行SQL语句并与数据库进行交互。
-
在用jdbc技术时,必须先获取connection对象(如果没有获取Connection对象后续的操作不复存在),Connection也代表的是一次链接,在使用完毕后,要释放资源,避免资源占用浪费和泄露。
2.3 Statement
2.4PreparedStatement
PreparedStatement是Statement接口的子接口,用于执行预编译的SQL查询,作用如下:
- 预编译SQL语句:在创建PreparedStatement时,就会预编译SQL,也就是SQL语句已经固定。
- 防止SQL注入:
PreparedStatement支持参数化查询,将数据作为参数传递到SQL语句中,采用?占位符的方式,将传入的参数用一对单引号(’’)包裹起来,无论传递什么都作为值,有效防止传入关键字或值导致SQL注入问题
- 性能提升:PreparedStatement是预编译SQL语句,同一SQL语句多次执行的情况下,可以复用,不必每次重新编译和解析。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.Chiba.base;
import java.sql.*;
import java.util.Scanner;
public class JDBCPrepared {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://localhost:3306/jdbcdemo";
String username = "root";
//password修改成自己设置mysql的密码
String password = "password";
//password修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
PreparedStatement preparedstatement = connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?");
Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
preparedstatement.setString(1,name);
ResultSet resultSet = preparedstatement.executeQuery();
while (resultSet.next()) {
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
double empSalary = resultSet.getDouble("emp_salary");
int empAge = resultSet.getInt("emp_age");
System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
}
resultSet.close();
preparedstatement.close();
connection.close();
}
}
|
1
|
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?;
|
如果用sql注入的话就是输入:abc’ or ‘1’=‘1,这时候abc' or '1'='1就会代替问号并且加上两边加上单引号:
1
|
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name='abc' or '1'='1';
|
这是后看着虽然和用Statement时候注入的形式一样,但是PreparedStatement会在他们中间加上转义字符,使得他们变成普通的值:
1
|
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name='abc\' or \'1\'=\'1';
|
**总结:**在实际应用中,不要使用Statement类,因为它有sql注入的漏洞,反而我们要统一的使用Statement的子类PreparedStatement类,它不仅可以防止sql注入还可以提高性能,因为它是预编译的,可以复用不需要每次都编译。总而言之,使用``PreparedStatement`更安全、更高效。
2.5ResultSet
ResultSet是JDBC API中的一个接口,用于从数据库中执行查询语句所返回的结果集,它提供了一种用于遍历和访问查询结果的方式。
- 遍历结果:
ResultSet可以使用**next()**方法将游标移动到结果集的下一行,逐行遍历数据库查询的结果,返回值为boolean类型,true表示有下一行的结果,false表示没有。
- 获取单列结果:可以通过getXxx的方法获取单列的数据,该方法为重载方法 ,支持索引和列名进行获取。
专业术语–ORM:
JDBC全流程:注册驱动—>获取连接—>预编译获取PreparedStatement对象—>编写并执行sql语句—>遍历结果集—>资源释放
案例—>CURD
查询–>单行单列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.Chiba.base;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestDemo {
public static void main(String[] args) throws Exception {
// 1.驱动注册
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接--->passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
// 3.预编译PreparedStatement对象
PreparedStatement preparStatement = connection.prepareStatement("select count(*) as count from t_emp");
// 4.获取返回值
ResultSet resultSet = preparStatement.executeQuery();
// 5.遍历值
while(resultSet.next()){
int count=resultSet.getInt("count");
System.out.println(count);
}
resultSet.close();
preparStatement.close();
connection.close();
}
}
|
查询–>单行多列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.Chiba.base;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
@Test
public void testQuerySingleRow() throws Exception {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接(url、name、password)--->passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","password");
//预编译获取preparedStatement对象
PreparedStatement preparedStatement=connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_id=?");
//给占位符赋值然后执行并获取结果集
preparedStatement.setInt(1,4);
ResultSet resultSet=preparedStatement.executeQuery();
//结果集遍历
while(resultSet.next()){
int empId=resultSet.getInt("emp_id");
String empName=resultSet.getString("emp_name");
Double empSalary=resultSet.getdouble("emp_salary");
int empAge=resultSet.getInt("emp_age");
System.out.println(empId+"\t"+empName+"\t"+empSalary+"\t"+empAge);
}
//关闭资源
resultSet.close();
preparedStatement.close();
connection.close();
}
}
|
查询–>多行多列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.Chiba.base;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
@Test
public void testQueryMoreRow() throws Exception {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接(url、name、password)--->passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
// 3.预编译获得preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_age>?");
// 4.为占位符赋值才能执行sql
preparedStatement.setInt(1, 25);
ResultSet resultSet = preparedStatement.executeQuery();
// 5.遍历
while (resultSet.next()) {
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
double empSalary = resultSet.getDouble("emp_salary");
int empAge = resultSet.getInt("emp_age");
System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
}
// 6.资源释放
resultSet.close();
preparedStatement.close();
connection.close();
}
}
|
增加数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.Chiba.base;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
@Test
public void testInsert() throws Exception {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接(url、name、password)-->passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
// 3.预编译获取preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp(emp_name,emp_salary,emp_age)values(?,?,?)");
preparedStatement.setString(1, "Mike");
preparedStatement.setDouble(2, 9999.99);
preparedStatement.setInt(3, 25);
int res = preparedStatement.executeUpdate();
// 根据受影响行数判断true或false;
if (res > 0) {
System.out.println("True");
} else {
System.out.println("False");
}
preparedStatement.close();
connection.close();
}
}
|
更改数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.Chiba.base;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
@Test
public void testUpdate() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
//passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
PreparedStatement preparedStatement = connection.prepareStatement(" update t_emp set emp_salary=? where emp_id=?;");
preparedStatement.setDouble(1, 10000);
preparedStatement.setInt(2, 6);
int res = preparedStatement.executeUpdate();
if (res > 0) {
System.out.println("True");
} else {
System.out.println("False");
}
// 关闭资源
preparedStatement.close();
connection.close();
}
}
|
删除数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package com.Chiba.base;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
@Test
public void testDelete() throws Exception {
// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接 --->passowrd修改为mysql设置的密码
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
// 预编译获取preparedStatement对象
PreparedStatement preparedStatement = connection.prepareStatement("delete from t_emp where emp_id=?");
// 给占位符赋值,执行sql语句获取结果集
preparedStatement.setInt(1, 7);
int result = preparedStatement.executeUpdate();
if (result > 0) {
System.out.println("True");
} else {
System.out.println("False");
}
// 关闭资源
preparedStatement.close();
connection.close();
}
}
|
在执行sql返回结果的时候:
如果是查询就用executeQuery()
如果是增删改就用executeUpdate()