PreparedStatement学习笔记

本文分享了作者从使用Statement到PreparedStatement的心得体会,并详细对比了两者之间的区别。文章中提到PreparedStatement可以预编译SQL语句,避免SQL拼接错误,提高程序的安全性和性能。
摘要由CSDN通过智能技术生成

之前一直用statement开发,statement对象作为将SQL语句发送到数据库的工具,非常的好用,我一般都是定义一个DBManager,先封装了statement对象的创建,和返回结果集的函数:

 

public Statement getStatement() {
		Connection connection = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/pinshan?useUnicode=true&characterEncoding=utf8&useSSL=true", "root", "root")
			connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/data?useUnicode=true&characterEncoding=utf8&useSSL=true", "root", "root");
			stmt = connection.createStatement();
		
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return stmt;
	}

public ResultSet query(String sql) {
		ResultSet rst = null;
		Statement stmt = getStatement();
		System.out.println("stmt = " + stmt);
		try {
			rst = stmt.executeQuery(sql);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return rst;
	}

 

这两天看书,书上强烈的介绍了preparedstatement,主要有三个好处:

1、预编译SQL语句,性能更好。

2、无须拼接SQL语句,不麻烦,不易出错,有利于编程和后期维护。

3、可以防止sql注入,安全性更好。

 

简直直击我心!!!

我总是担心sql注入,怕谁给我把用户信息删了,或者黑我服务器什么的。前端的监控能力是有限的,sql注入难以幸免。 所以有了这个preparedstament,我是无论何如要试试看的。

 

首先是把DBManager的方法换了:

这里注意要返回一个PreparedStatement类型。

 

public PreparedStatement getPreStatement(String sql) {
		Connection connection = null;
		  PreparedStatement ps=null; 
		try {
			Class.forName("com.mysql.jdbc.Driver");
			connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/data?useUnicode=true&characterEncoding=utf8&useSSL=true", "root", "root");
			ps=connection.prepareStatement(sql);
		
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return ps;
	}

然后就是把之前的拼接字段全部改成“?”占位符,然后调用PreparedStatement的方法去填充它。 这里不满意的是,居然不能一起填充了,要位置和内容一一对应,一个一个填充。开始我少填了一个,编译直接报错了,我觉得不错还挺好的,之前用statement开发,因为少写了 , 或者是 )编译不报错,测试的时候才出错,这其实是不好的。

 

String sqls = "update pinshan.goto shan SET shan=? where username=?" ;
		preparedStatement=db.getPreStatement(sqls);
		preparedStatement.setString(1,shan);
		preparedStatement.setString(2,username);
		preparedStatement.execute();

最后就是这个错:

 

Exception in thread "main" java.sql.SQLException:Can not issue data manipulation statements with executeQuery().

    atcom.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)

    atcom.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)

    atcom.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)

    atcom.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)

    atcom.mysql.jdbc.StatementImpl.checkForDml(StatementImpl.java:463)

    atcom.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1926)

这是preparedStatement.execute();preparedStatement.executeQuery(sql);的用法没有搞清楚的关系。

一句话,execute()的返回值是布尔类型,就是返回正确执行了没有,而executeQuery是返回查询的结果集的,需要赋给左边的结果集。

ResultSet rst=preparedStatement.executeQuery(sql);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值