SQL动态参数绑定
场景:
向数据库添加一条数据,字段数据由用户输入决定。
思路:
用户通过界面,输入数据并提交给Java程序,java程序通过JDBC技术,将数据插入到MySQL中。
1. 字符串拼接
💡JDBC中的SQL语句本质上是一个String字符串。可以通过把参数和SQL进行String拼接。
语法:
String sql = "insert into t_person values(null,'"+arg1+"',"+arg2+",'"+arg3+"','"+arg4+"','"+arg5+"')";
String sql = "select * from t_person where id = "+id变量;
示例:
# 参数
String name = "宇希";
String sex = "男";
int age = 28;
String mobile = "15533368877";
String address = "北京";
# 绑定
String sql = "insert into t_person values(null,'"+name+"',"+age+",'"+sex+"','"+mobile+"','"+address+"')";
2. 占位符
💡使用**
?标记
动态参数在SQL中位置,然后使用编码,动态将参数绑定到?站位
**的位置。
语法:
① SQL中使用?标记站位
注意:?站位只能表示数据,其他(sql关键词、表名、字段名等)都不能使用?站位。
insert into t_person values(null,?,?,?,?,?);
② 动态绑定参数
注意,参数绑定的参数位置和顺序必须和?站位保持一致。
1. 增删改DML的方法参数绑定
update(String sql, @Nullable Object... args);
2. DQL查询语句的方法参数绑定
query(String sql, RowMapper<T> rowMapper, @Nullable Object... args);
示例:
# 1. 参数
String name = "宇希";
String sex = "男";
int age = 28;
String mobile = "";
String address = "";
# 2. SQL并使用?站位
String sql = "insert into t_person values(null,?,?,?,?,?)";
# 3. 动态参数绑定并发送SQL
jdbcTemplate.update(String sql, name,age,sex,mobile,address);
3. SQL注入
💡通过输入特殊的参数拼接SQL语句,进而破坏原有的SQL语句的含义,然后非法获取数据库数据或者进行非法数据库操作,是一种常见的web安全漏洞。
场景:用户通过输入username和password,判断是否能够登录成功。
SQL注入参数:
String adminName = "xiaohei'-- ";//真实用户名后添加'-- ,后面的内容会被注释掉
String adminPassword = "1234567";//密码错误,但也能登录成功
- 字符串拼接
-
?站位
-
结论
?站位方式可以防止SQL注入问题。
4. 总结
字符串拼接 | ?站位 | |
---|---|---|
相同 | 动态拼接sql中的数据参数 | 动态拼接SQL中的数据参数 |
不同 | 可以绑定非数据的参数:表名、字段名、SQL关键字 | 只能绑定数据,不能绑定其他SQL关键词和表名字段名 |
有SQL注入风险 | 可以防止SQL注入。 | |
建议场景 | 适用于拼接表名、字段名、SQL关键词 | 适用于拼接数据参数 |
四 连接池
问题:
- 每次JDBC访问MySQL,都需要一个Connection对象。
- 一个Connection对象创建,需要经历(开辟内存空间、初始化数据、建立java和MySQL之间的io连接,最后完成Connection的创建),这个过程会消耗CPU资源和JVM内存资源。
- 如果使用完Connection,就销毁掉,会让Connection对象创建消耗的资源白白浪费掉。
解决思路:
1. 事先创建好一个管理器容器,内部准备好一定数量的连接池。(只做一次)
2. 当Java访问数据库需要用连接的时候, 直接从连接池中获取一个conn对象。(避免了创建conn过程消耗的时间,效率高。)
3. 使用完毕conn之后,将conn还回连接池。(以备重复利用)
连接池:
💡对一定数量的Connection对象,进行池化管理,可以重复利用connection对象,节约CPU和JVM内存资源。
编码:
//1 创建,并配置DataSource
String url = "jdbc:mysql://localhost:3306/baizhi?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "123456";
DataSource dataSource = new DriverManagerDataSource(url,username,password);
五 异常调试
1. 常见JDBC异常
SQLException: No value specified for parameter 1
-
错误信息:控制台输入对应的值后 抛出SQL异常
-
原因: sql语句中使用了?占位符,但是没有给占位符赋值
//执行sql PreparedStatement pstm = conn.prepareStatement("delete from t_product where product_name=?"); //执行sql pstm.executeUpdate();
-
解决方案:
给?占位符赋值即可;
//执行sql PreparedStatement pstm = conn.prepareStatement("delete from t_product where product_name=?"); //这里给 ? 占位符 赋值 pstm.setString(1,name);