java预编译语句_JDBC04----预编译语句介绍

sql的拼接很麻烦,且容易出错,因此就可以使用预编译语句。

接口java.sql.Statement有两个子接口:CallableStatement,PreparedStatement

有两种类型的sql语句:

1.静态sql

在执行之前就知道了sql语句的形式。

2.动态sql

一. Statement接口的实现类

1. PreparedStatement

PreparedStatement用于预编译模板SQL语句,在运行时接受SQL输入参数。eg:PreparedStatement ps=conn.preparedStatement(sql);

在性能和代码灵活性上有显著的提高

PreparedStatement对象使用?作为占位符,即参数标记;eg:  select *from stu where id=?;  insert into stu value(?,?,?);

使用setXXX(index,value)方法将值绑定到参数中,每个参数标记是其顺序位置引用,注意index从1开始;eg:ps.setInt(1,stu.getId());

PreparedStatement对象执行sql语句:executeQuery()、executeUpdate(),注意,他们没有参数; eg:ps.executeUpdate();

2. 举例

public Stu get(intid) {

ResultSet resultSet=null;

Connection connection=null;

PreparedStatement pStatement=null;

Stu student=newStu();try{

Class.forName(JDBCUtil.driverName);

connection=JDBCUtil.getConnection();

String sql="select *from stu where id=?";

pStatement=connection.prepareStatement(sql);

pStatement.setInt(1, id);//note这里的id时传入的,如果传入参数是student,就可以改成pStatement.setInt(1,student.getId())

resultSet=pStatement.executeQuery();if(resultSet.next()) {

student.setId(resultSet.getInt("id"));

student.setName(resultSet.getString("name"));

student.setAge(resultSet.getInt("age"));returnstudent;

}

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}finally{

JDBCUtil.close(connection, pStatement, resultSet);

}return null;

}

3. 如果没有使用预编译语句

如果没有使用预编译语句的话,假设已经有一个静态的sql语句了,每一次查找的age不同,都会往预编池中写入一次数据。

4. 如果使用预编译语句

参数统一用?表示,这样预编译池中就不会多次写入数据了。---------(当很多人操作数据库时,这回很麻烦的)

note: mysql不支持预编译池,oracle支持预编译池。

cc1af19c5e202bad3efe6725347769c6.png

6. 使用预编译可以防止SQL注入。

(1)什么是SQL注入(note: 后面文章还会补充关于SQL注入以及如何防止SQL注入的知识!!!,这里只是先简单了解下)

就是通过把SQL命令插入到WEB表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL语句。(说人话:就是一些错误的sql语句,导致了错误的sql语义被执行了)

(2)SQL注入举例

3feb5f536d64791342d4169d24e1c19b.png

上面是一个用户登陆的代码,当用户名如上定义时,虽然表中没有这个用户,但是最终的结果会发现打印了登陆成功。打印出这一条sql语句:

7168ffd8bc906c8008724ab3808c8f9e.png

因此,看到拼接结果可以知道前面那个条件已经满足了,就不会管or后面的语句了:即name=‘’已经成立了。

如果使用预编译,因为它执行的时候会把单引号转义。----也就是防止SQL注入的根源

如果使用预编译:

3b6e6e549c46f818a590b4bd7a5eaf29.png

82cf27ad3abfc4049ce65c60d8791aff.png

(3)为什么PrepareStaet就能防止注入

是因为它把单引号转义了,变成了\,这样一来,就无法截断SQL语句,进而无法拼接SQL语句,基本上没有办法注入了。

二. JDBC调用输出参数存储过程----CallableStatement

1. 创建一个存储过程

c8657cc4ae153f1d713669a225ece5bc.png

测试下:

535f364b4fe17af39617d2330d2e085b.png

2. 使用Java程序来实现调用

public voidcall(){

Connection connection=JDBCUtil.getConnection();

CallableStatement cStatement;try{

cStatement= connection.prepareCall("{call getName(?,?)}");

cStatement.setInt(1, 2);

cStatement.registerOutParameter(2, Types.VARCHAR);

cStatement.execute();

String name=cStatement.getString(2);

System.out.println(name);

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

参考文献

https://ke.qq.com/course/339214

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值