目录
四、SQl注入和预状态通道PreparedStatement
JDBC是一种用于执行SQL语句的Java API,可以在各种平台上使用Java,如Windows,Mac OS和各种版本的UNIX。
一、JDBC核心组件
DriverManager: 此类管理数据库驱动程序列表。使用通信子协议将来自java应用程序的连接请求 与适当的数据库驱动程序匹配。
Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用 DriverManager对象来管理这种类型的对象。
Connection:该界面具有用于联系数据库的所有方法。连接对象表示通信上下文,即,与数据库 的所有通信仅通过连接对象。
Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派 生接口还接受参数。
ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一 个迭代器,允许我们移动其数据。
SQLException:此类处理数据库应用程序中发生的任何错误
二、使用步骤
构建JDBC应用程序涉及以下六个步骤:
- 导入包:需要包含包含数据库编程所需的JDBC类的包。大多数情况下,使用import java.sql.*就足够 了。
- 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。
- 打开连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表 示与数据库的物理连接。
- 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。
- 从结果集中提取数据:需要使用相应的ResultSet.getXXX()方法从结果集中检索数据。
- 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。
三、连接步骤
1.导包
import java.sql.*
2.注册JDBC驱动程序:
工程下创建lib文件夹,把mysql-connector压缩包放入lib下,点击左上角文件复选框-项目结构,打开此界面,点击依赖
点击+,单击第一个JAR或目录,找到刚刚的lib文件下压缩包,点击确定注入。
3.数据库URL配置,创建连接对象
这是为了创建一个格式正确的地址,指向要连接到的数据库。
(1)加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");//从本地工程加载驱动
(2)获得链接
创建数据库连接对象
String userName = "root";//数据库用户名
String userPassword = "123456";//数据库密码
String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//数据库mysql8 URL配置
Connection connection = DriverManager.getConnection(url,userName, userPassword);
加载驱动程序后,可以使用DriverManager.getConnection()方法建立连接。
- getConnection(String url)
- getConnection(String url,Properties prop)
- getConnection(String url,String user,String password)
完整的连接地址:
第一种:jdbc:mysql://localhost:3306/yhp2?serverTimezone=UTC
localhost:数据库地址,本地就是这个 3306:数据库所用的端口 yhp2:要打开的数据库名
第二种:jdbc:mysql://localhost:3306/数据库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8
(3)定义sql,创建状态通道
Statement statement = connection.createStatement();
ResultSet resultSet=statement.executeQuery("select * from student;");//执行查询
while (resultSet.next()) {
System.out.println("编号:"+resultSet.getInt("stuid")
+"\t姓名" +resultSet.getString("name")
+"\t\t生日"+resultSet.getDate("birthday"));
}
执行查询的语句:返回的是一个结果集(executeQuery)
resultSet=statement.executeQuery("select * from student;");
执行增删改的语句,返回数大于0成功,否则失败。(executeUpdate)
int i=statement.executeUpdate("update student set birthday='1011-1-1' ");
ResultSet:
用resultset接收结果集
(4)关闭资源
resultSet.close();
statement.close();
connection.close();
(5)完整代码
import java.sql.*;
public class Demo1 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String userName = "root";
String userPassword = "123456";
String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";
connection = DriverManager.getConnection(url, userName, userPassword);
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from student;");
while (resultSet.next()) {
System.out.println("编号:" + resultSet.getInt("stuid")
+ "\t姓名" + resultSet.getString("name")
+ "\t\t生日" + resultSet.getDate("birthday"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
四、SQl注入和预状态通道PreparedStatement
现在网站比较安全,但还是要考虑到。sql注入就是在执行sql语句的时候,比如输入密码的时候夹带别的对数据库安全有威胁的sql语句,如密码输入 or 1=1;那样条件恒等,就可以随便进入
预状态通道,PreparedStatement此种方式将sql语句中的输入用?代替,确保sql语句的本块在传到了数据库执行时带有引号如错误密码变成了 ' 123456 or 1=1',因为有了引号就都变成了字符串,or不会再被当成条件执行,之后按照从1开始1的下标顺序以此给?赋值
此代码块和第三模块第(3)定义sql,创建状态通道相通,经过更改后变成下面,换了案例,用用户名和密码为例子
String sql = "select * from userVIP where userName=? and userPass=?";//问号占位
PreparedStatement preparedStatement = connection.prepareStatement(sql);//PreparedStatement接收数据
preparedStatement.setString(1, "张三");//按照从1开始的下标顺序给sql语句中的问号赋值
preparedStatement.setString(2, "123456");
resultSet = preparedStatement.executeQuery();
解决了sql注入后的完整代码
import java.sql.*;
public class Demo1 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String userName = "root";
String userPassword = "123456";
String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";
;
connection = DriverManager.getConnection(url, userName, userPassword);
String sql = "select * from userVIP where userName=? and userPass=?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "张三");
preparedStatement.setString(2, "123456");
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println("编号:"+resultSet.getInt("id")
+"\t用户名" +resultSet.getString("userName")
+"\t\t密码"+resultSet.getString("userPass"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
五、多表操作
一对多,多对一,一对一,多对多
记录一个多对多
一个学生可以学很多课程,一个课程也可以有很多学生在学,形成多对多关系。
1.创建bean下的实体
Student
package bean;
import java.util.List;
public class Student {
private int stuid;
private String stuname;
private int teacherid;
private List<Subject> subjects;
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getTeacherid() {
return teacherid;
}
public void setTeacherid(int teacherid) {
this.teacherid = teacherid;
}
public List<Subject> getSubjects() {
return subjects;
}
public void setSubjects(List<Subject> subjects) {
this.subjects = subjects;
}
}
Subject
package bean;