Java中的JDBC
JDBC:Java Database Connectivity
JDBC Statement与PreparedStatement的区别
参考:https://www.jianshu.com/p/8afaf935d073 https://www.jianshu.com/p/d73e83bb5d7d
作者:疯癫的猪猪猪1、 PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。
2、作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。三种方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数
3、使用“?”占位符提升代码的可读性和可维护性.
4、使用 PreparedStatement 最重要的一点好处是它拥有更佳的性能优势,SQL语句会预编译在数据库系统中。执行计划同样会被缓存起来,它允许数据库做参数化查询。
5、PreparedStatement可以防止SQL注入式攻击。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行
链接:https://www.jianshu.com/p/d73e83bb5d7d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。1.PreparedStatement接口继承了Statement,PreparedStatement实例包含已编译的SQL语句,所以其执行速度要快于Statement对象。
2.作为Statement的子类,PreparedStatment继承了Statement的所有功能。三种方法execute,executeQuery和executeUpdate已被更改以使之不再需要参数。
3.在JDBC应用中,在任何时候都不要是使用Statement,原因如下:
1)、代码的可读性和可维护性。Statement需要不断地拼接,而PreparedStatement不会。
2)、PreparedStatement尽最大可能提高性能。DB有缓存机制,相同的预编译语句再次被调用不会再次需要编译。
3)、最重要的一点是极大的提高了安全性。Statement容易被SQL注入,而PreparedStatement传入的内容和参数不会和sql语句发生任何匹配关系。
例子
1. Statement的例子
View Code
View Code
View Code
JDBCUtil类:
View Code
// JDBC 的简单使用例子(Statement) Properties props = new Properties(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); props.load(loader.getResourceAsStream("db.properties")); String driver = props.getProperty("db.driver"); String url = props.getProperty("db.url"); String dbUser = props.getProperty("db.user"); String dbPassword = props.getProperty("db.password"); String sql = "select s.id,s.name,t.name from tb_teachers t, tb_students s where t.id = s.teacher_id"; Connection conn = null; Statement stm = null; ResultSet rs = null; try{ //1. 使用反射,加载驱动 Class.forName(driver); //2. 使用DriverManager 获取数据库连接 conn = DriverManager.getConnection(url, dbUser, dbPassword); //3. 使用Connection 来创建一个Statement对象 stm = conn.createStatement(); //4. 执行sql语句 (有三种:execute, excuteQuery, excuteUpdate) rs = stm.executeQuery(sql); //5. 遍历查询结果 System.out.println("学号\t姓名\t老师"); while(rs.next()) { System.out.println(rs.getInt(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3)); } }catch(Exception e){ e.printStackTrace(); }finally{ // 释放资源 if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stm!=null){ try { stm.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
2. PrepareStatement的例子
Properties props = new Properties(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); props.load(loader.getResourceAsStream("db.properties")); String driver = props.getProperty("db.driver"); String url = props.getProperty("db.url"); String dbUser = props.getProperty("db.user"); String dbPassword = props.getProperty("db.password"); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try{ //1. 使用反射,加载驱动 Class.forName(driver); //2. 使用DriverManager 获取数据库连接 conn = DriverManager.getConnection(url, dbUser, dbPassword); //3. 使用Connection 来创建一个PreparedStatement对象 ps = conn.prepareStatement("insert into tb_students(id,name,teacher_id) values(?,?,?)"); // ps.setInt(1, 3); ps.setString(1, "4"); ps.setString(2, "马丁2"); ps.setString(3, "1001"); //4. 执行sql语句 ps.executeUpdate();//INSERT, UPDATE or DELETE 语句 }catch(Exception e){ e.printStackTrace(); }finally{ // 释放资源 if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
3. 使用自己封装的工具类
Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try{ //1. 获取数据库连接 conn = JDBCUtil.getConnection(); //2. 使用Connection 来创建一个PreparedStatement对象 ps = conn.prepareStatement("select * from tb_students where id=? and name=?"); ps.setInt(1, 2); ps.setString(2, "Wang"); //3. 执行sql语句 rs = ps.executeQuery(); //4. 遍历查询结果 while(rs.next()) { System.out.println(rs.getString(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3)); } }catch(Exception e){ e.printStackTrace(); }finally{ // 释放资源 JDBCUtil.closeAll(rs, ps, conn); }
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ResourceBundle; public class JDBCUtil { private JDBCUtil(){} private static String driverClass; private static String url; private static String username; private static String password; static{ //此对象是用于加载properties文件数据的 //命名格式为:配置文件名_语言代码_国家代码.properties,在没有加“语言代码_国家代码”的情况下 //ResourceBundle默认读取的是系统所使用地区码的配置文件, //例子中,系统默认为zh_CN,所以读取的就是zh_CN结尾的配置文件。 ResourceBundle rb = ResourceBundle.getBundle("db");//在classpath下,先找 db_zh_CN.properties, 若无, 再找 db.properties, 再无,异常。 driverClass = rb.getString("db.driver"); url = rb.getString("db.url"); username = rb.getString("db.user"); password = rb.getString("db.password"); try { Class.forName(driverClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //得到连接的方法 public static Connection getConnection() throws Exception{ return DriverManager.getConnection(url, username, password); } //关闭资源的方法 public static void closeAll(ResultSet rs,Statement stmt,Connection conn){ //关闭资源 if(rs!=null){ try { rs.close(); } catch (Exception e) { e.printStackTrace(); } rs = null; } if(stmt!=null){ try { stmt.close(); } catch (Exception e) { e.printStackTrace(); } stmt = null; } if(conn!=null){ try { conn.close(); } catch (Exception e) { e.printStackTrace(); } conn = null; } } }
配置文件db.properties 放在src下,内容如下
# mysql驱动 db.driver=com.mysql.jdbc.Driver # 数据库url db.url=jdbc:mysql://127.0.0.1:3306/shop # 数据库用户名 密码 db.user=root db.password=123456
常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。