statement与preparedStatement的使用及区别
首先,PreparedStatemen继承自statement接口,区别有以下几点:
- statement是执行静态sql语句的,而preparedStatement是执行预编译,因此语法上也有区别。
- preparedStatement在执行大量的相同sql语句上(例如插入一万条数据)效率比statement高。因为statement每次只能发送一条sql语句,每次发送到数据库对应的数据 库都需要编译sql语句;而preparedStatement只需要编译一次即可。如果只执行一次,则选则statement。
代码测试如下:
@Test
public void testStatement(){
try {
Connection connection=JDBCUtil.getConnection();
Statement stat=connection.createStatement();
String sql="insert into student(name,gender) values('张三','男')";
//测试插入一万条数据
long startTime=System.currentTimeMillis();
for(int i=0;i<1000;i++){
stat.executeUpdate(sql);
}
long endTime=System.currentTimeMillis();
System.out.println("耗时:"+(endTime-startTime)/1000+"秒");//43秒
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Test
public void testPrepared(){
Connection connection = JDBCUtil.getConnection();
PreparedStatement stat=null;
String sql="insert into student(name,gender) values(?,?)";
String name="张三";
String gender="男";
try {
long startTime=System.currentTimeMillis();
stat=connection.prepareStatement(sql);
for(int i=0;i<1000;i++){
stat.setString(1, name);
stat.setString(2, gender);
stat.executeUpdate();
}
long endTime=System.currentTimeMillis();
System.out.println("耗时:"+(endTime-startTime)/1000+"秒");//28秒
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCUtil.clear(stat, connection);
}
}
- preparedStatement可以防止恶意sql注入。那么什么是sql注入呢?简单点说,我们通过拼接动态构建sql语句是,用户发送恶意的sql语句到数据库服务器,而我们的服务器又没有过滤直接执行了该sql语句,就可能造成意外的后果。
下面通过一个登陆案例说明:
//使用statement测试安全性
@Test
public void test1(){
Connection connection=null;
Statement statement=null;
String name ="eric' or 1=1 -- ";//使用该语法就可以使用万能密码
String pwd="";
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获取connection连接对象
connection = DriverManager.getConnection(url, user, password);
//获取statement对象
statement=connection.createStatement();
//执行
String sql="select *from student where name='"+name+"'and password='"+pwd+"'";
ResultSet rs=statement.executeQuery(sql);//返回结果集
if(rs.next()){
System.out.println("登录成功");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//关闭资源
try {
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
测试证明无论输入任何密码都登陆成功。