JDBC——(1)JDBC概述
JDBC——(2)数据持久化的含义和Java中的数据存储技术
JDBC——(3) JDBC程序操作和访问数据库步骤
JDBC——(4)获取数据库连接
JDBC——(4)获取数据库连接——方式一
JDBC——(4)获取数据库连接——方式二
JDBC——(4)获取数据库连接——方式三
JDBC——(4)获取数据库连接——方式四
JDBC——(4)获取数据库连接——方式五(最终版)
JDBC——小知识 :Class.forName(“com.mysql.jdbc.Driver”)的浅谈
JDBC——(5)使用Statement操作数据表的弊端
JDBC——(6)PreparedStatement的使用
JDBC——小知识:封装数据库连接和关闭操作
JDBC——(6)PreparedStatement的使用——实现通用的增删改操作
JDBC——(6)PreparedStatement的使用——增、删、改示例演示
JDBC——(6)PreparedStatement的使用——实现查询操作
JDBC——(6)PreparedStatement的使用——实现通用的查询操作
JDBC——小知识:PreparedStatement 和Statement的比较
JDBC—— 小知识:Java与SQL对应数据类型转换表
JDBC——(6)PreparedStatement的使用——查询示例演示
JDBC——小知识:ResultSet与ResultSetMetaData
JDBC——小知识:资源的释放
JDBC——(6)PreparedStatement的使用——图解查询操作流程
JDBC——(6)PreparedStatement的使用——针对不同表的查询操作
JDBC——(6)PreparedStatement的使用——批量插入数据
JDBC——(7)JDBC API小结
JDBC——(8)数据库连接池技术的概述
JDBC——(8)数据库连接池技术的概述——Druid数据库连接池技术的实现
JDBC——小知识:Druid连接池的详细配置参数
一,操作和访问数据库
-
数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
-
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
- Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
- PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
- CallableStatement:用于执行 SQL 存储过程
二,使用Statement操作数据表的弊端
- 通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。如下代码演示
Connection conn = null;
Statement st = null;
conn=JDBCUtils.getConnection();//已经封装好的连接
st = conn.createStatement();
-
Statement 接口中定义了下列方法用于执行 SQL 语句:
int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE ResultSet executeQuery(String sql):执行查询操作SELECT
-
但是使用Statement操作数据表存在弊端:
- 问题一:存在拼串操作,繁琐
- 问题二:存在SQL注入问题
-
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
-
对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。
代码演示:
package com.atguigu2.statement.crud;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;
import org.junit.Test;
public class StatementTest {
// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
//如何避免出现sql注入:只要用 PreparedStatement(从Statement扩展而来) 取代 Statement
@Test
public void testLogin() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:");
String user = scanner.nextLine();
System.out.print("请输入密码:");
String password = scanner.nextLine();
//SELECT user,password FROM user_table WHERE user = '1' or ' AND password = '=1 or '1' = '1'
String sql = "SELECT user,password FROM user WHERE user = '"+ user +"' AND password = '"+ password +"'";
User returnUser = get(sql,User.class);
if(returnUser != null){
System.out.println("登录成功");
}else{
System.out.println("用户名不存在或密码错误");
}
}
// 使用Statement实现对数据表的查询操作
public <T> T get(String sql, Class<T> clazz) {
T t = null;
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 1.加载配置文件
InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
// 2.读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 3.加载驱动
Class.forName(driverClass);
// 4.获取连接
conn = DriverManager.getConnection(url, user, password);
st = conn.createStatement();
rs = st.executeQuery(sql);
// 获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
// 获取结果集的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
// //1. 获取列的名称
// String columnName = rsmd.getColumnName(i+1);
// 1. 获取列的别名
String columnName = rsmd.getColumnLabel(i + 1);
// 2. 根据列名获取对应数据表中的数据
Object columnVal = rs.getObject(columnName);
// 3. 将数据表中得到的数据,封装进对象
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, columnVal);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return null;
}
}
数据库中没有这个用户名和密码却可以登录成功
综上: