前面提到Statement存在拼串、和sql注入的问题。
PreparedStatement的代码有更好的可读性和可维护性。能很大程度上提高性能。
DBService会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配没有缓存语句的意义,事实是没有数据库回对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
语法检查、语义检查、翻译成二进制命令、缓存
PreparedStatement可以防止SQL注入。
除此之外,PreparedStatement还有如下两个好处:
1、PreparedStatement可以操作Blob类型的字段,而Statement做不到。
2、PreparedStatement可以实现高效的批量操作。
操作Blob类型
接下来介绍一下Blob类型
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接。
MySQL的四种BLOB类型除了在存储的最大信息上不同外,它们是等同的。
类型 | 大小(单位,字节) |
---|---|
TinyBlob | 最大255 |
Blob | 最大65K |
MediumBlob | 最大16M |
LongBlob | 最大4G |
实际使用中根据需要存入的数据大小定义不同的BLOB类型;
需要注意的是:如果存储的文件过大,数据库的性能会下降;
如果指定了相关的Blob类型后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下配置参数:max_allowed_packet=16M,同时注意:修改了my.ini文件后,需要重启mysql服务。
向表中插入Blob类型的字段的语句如下所示:
String sql = "insert into customers(name,email,birth,photo) values(?,?,?,?)";//这里的photo是图片,Blob类型的数据
ps = conn.prepareStatement(sql);
ps.setObject(1, "李白");
ps.setObject(2, "libai@qq.com");
ps.setObject(3, "2000-02-02");
FileInputStream is = new FileInputStream(new File("04.JPG"));
ps.setObject(4, is);//将photo以流的形式填充占位符
ps.execute();//执行sql
查询表中Blob类型的字段的语句如下所示:
//获取连接后,填充占位符
String sql = "select id,name,email,birth,photo from customers where id = ?";
ps = conn.prepareStatement(sql);
ps.setObject(1, 24);
rs = ps.executeQuery();
if(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birth");
//这里是因为在项目中有一个Customer类,所以将查到的这些字段封装为一个customer对象
Customer cust = new Customer(id, name, email, birth);
System.out.println(cust);
//将Bolb类型的字段下载下来,以文件的方式保存在本地
Blob photo = rs.getBlob("photo");
is = photo.getBinaryStream();//该方法产生一个Input Stream输入流
fos = new FileOutputStream("test.jpg");//再创建一个FileOutputStream输出流将数据保存在本地
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
如有错误或不足,欢迎大家留言指正。