2017.6.27 jdbc基本使用
参考来自:http://www.runoob.com/w3cnote/jdbc-use-guide.html
1.jdbc的执行流程
JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。
执行流程:
-
连接数据源,如:数据库。
-
为数据库传递查询和更新指令。
-
处理数据库响应并返回的结果。
2.jdbc的编程步骤
2.1 加载驱动程序
Class.forName(driverClass) //加载MySql驱动 Class.forName("com.mysql.jdbc.Driver") //加载Oracle驱动 Class.forName("oracle.jdbc.driver.OracleDriver")
2.2 获得数据库连接
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/imooc", "root", "root");
2.3 创建Statement\PreparedStatement对象
conn.createStatement();
conn.prepareStatement(sql);
2.4 执行操作
1 import java.sql.Connection; 2 import java.sql.DriverManager; 3 import java.sql.ResultSet; 4 import java.sql.Statement; 5 6 public class DbUtil { 7 8 public static final String URL = "jdbc:mysql://localhost:3306/imooc"; 9 public static final String USER = "liulx"; 10 public static final String PASSWORD = "123456"; 11 12 public static void main(String[] args) throws Exception { 13 //1.加载驱动程序 14 Class.forName("com.mysql.jdbc.Driver"); 15 //2. 获得数据库连接 16 Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); 17 //3.操作数据库,实现增删改查 18 Statement stmt = conn.createStatement(); 19 ResultSet rs = stmt.executeQuery("SELECT user_name, age FROM imooc_goddess"); 20 //如果有数据,rs.next()返回true 21 while(rs.next()){ 22 System.out.println(rs.getString("user_name")+" 年龄:"+rs.getInt("age")); 23 } 24 } 25 }
3.完整示例
1 public class DbUtil { 2 public static final String URL = "jdbc:mysql://localhost:3306/imooc"; 3 public static final String USER = "liulx"; 4 public static final String PASSWORD = "123456"; 5 private static Connection conn = null; 6 static{ 7 try { 8 //1.加载驱动程序 9 Class.forName("com.mysql.jdbc.Driver"); 10 //2. 获得数据库连接 11 conn = DriverManager.getConnection(URL, USER, PASSWORD); 12 } catch (ClassNotFoundException e) { 13 e.printStackTrace(); 14 } catch (SQLException e) { 15 e.printStackTrace(); 16 } 17 } 18 19 public static Connection getConnection(){ 20 return conn; 21 } 22 }
1 package liulx.dao; 2 3 import liulx.db.DbUtil; 4 import liulx.model.Goddess; 5 6 import java.sql.Connection; 7 import java.sql.ResultSet; 8 import java.sql.SQLException; 9 import java.sql.Statement; 10 import java.util.ArrayList; 11 import java.util.List; 12 13 public class GoddessDao { 14 //增加 15 public void addGoddess(Goddess g) throws SQLException { 16 //获取连接 17 Connection conn = DbUtil.getConnection(); 18 //sql 19 String sql = "INSERT INTO imooc_goddess(user_name, sex, age, birthday, email, mobile,"+ 20 "create_user, create_date, update_user, update_date, isdel)" 21 +"values("+"?,?,?,?,?,?,?,CURRENT_DATE(),?,CURRENT_DATE(),?)"; 22 //预编译 23 PreparedStatement ptmt = conn.prepareStatement(sql); //预编译SQL,减少sql执行 24 25 //传参 26 ptmt.setString(1, g.getUser_name()); 27 ptmt.setInt(2, g.getSex()); 28 ptmt.setInt(3, g.getAge()); 29 ptmt.setDate(4, new Date(g.getBirthday().getTime())); 30 ptmt.setString(5, g.getEmail()); 31 ptmt.setString(6, g.getMobile()); 32 ptmt.setString(7, g.getCreate_user()); 33 ptmt.setString(8, g.getUpdate_user()); 34 ptmt.setInt(9, g.getIsDel()); 35 36 //执行 37 ptmt.execute(); 38 } 39 40 public void updateGoddess(){ 41 //获取连接 42 Connection conn = DbUtil.getConnection(); 43 //sql, 每行加空格 44 String sql = "UPDATE imooc_goddess" + 45 " set user_name=?, sex=?, age=?, birthday=?, email=?, mobile=?,"+ 46 " update_user=?, update_date=CURRENT_DATE(), isdel=? "+ 47 " where id=?"; 48 //预编译 49 PreparedStatement ptmt = conn.prepareStatement(sql); //预编译SQL,减少sql执行 50 51 //传参 52 ptmt.setString(1, g.getUser_name()); 53 ptmt.setInt(2, g.getSex()); 54 ptmt.setInt(3, g.getAge()); 55 ptmt.setDate(4, new Date(g.getBirthday().getTime())); 56 ptmt.setString(5, g.getEmail()); 57 ptmt.setString(6, g.getMobile()); 58 ptmt.setString(7, g.getUpdate_user()); 59 ptmt.setInt(8, g.getIsDel()); 60 ptmt.setInt(9, g.getId()); 61 62 //执行 63 ptmt.execute(); 64 } 65 66 public void delGoddess(){ 67 //获取连接 68 Connection conn = DbUtil.getConnection(); 69 //sql, 每行加空格 70 String sql = "delete from imooc_goddess where id=?"; 71 //预编译SQL,减少sql执行 72 PreparedStatement ptmt = conn.prepareStatement(sql); 74 //传参 75 ptmt.setInt(1, id); 77 //执行 78 ptmt.execute(); 79 }
80 //批量查询 81 public List<Goddess> query() throws SQLException { 82 Connection conn = DbUtil.getConnection(); 83 Statement stmt = conn.createStatement(); ??? PreparedStatement和statement的区别是什么???见下面(ps:这里不需要参数,可以直接用statement)。 84 ResultSet rs = stmt.executeQuery("SELECT user_name, age FROM imooc_goddess"); 85 86 List<Goddess> gs = new ArrayList<Goddess>(); 87 Goddess g = null; 88 while(rs.next()){ 89 g = new Goddess(); 90 g.setUser_name(rs.getString("user_name")); 91 g.setAge(rs.getInt("age")); 93 gs.add(g); 94 } 95 return gs; 96 }
97 //单个查询 98 public Goddess querySingle(){ 99 Goddess g = null; 100 //获取连接 101 Connection conn = DbUtil.getConnection(); 102 //sql, 每行加空格 103 String sql = "select * from imooc_goddess where id=?"; 104 //预编译SQL,减少sql执行 105 PreparedStatement ptmt = conn.prepareStatement(sql);??? PreparedStatement和statement的区别是什么???见下面。 106 //传参 107 ptmt.setInt(1, id); 108 //执行 109 ResultSet rs = ptmt.executeQuery(); 110 while(rs.next()){ 111 g = new Goddess(); 112 g.setId(rs.getInt("id")); 113 g.setUser_name(rs.getString("user_name")); 114 g.setAge(rs.getInt("age")); 115 g.setSex(rs.getInt("sex")); 116 g.setBirthday(rs.getDate("birthday")); 117 g.setEmail(rs.getString("email")); 118 g.setMobile(rs.getString("mobile")); 119 g.setCreate_date(rs.getDate("create_date")); 120 g.setCreate_user(rs.getString("create_user")); 121 g.setUpdate_date(rs.getDate("update_date")); 122 g.setUpdate_user(rs.getString("update_user")); 123 g.setIsDel(rs.getInt("isdel")); 124 } 125 return g; 126 } 127 }
4.PreparedStatement和statement的区别是什么
参考来自:http://www.importnew.com/5006.html
PreparedStatement是用来执行SQL查询语句的API之一。
Java提供了 Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句:
Statement 用于通用查询
PreparedStatement 用于执行参数化查询
CallableStatement则是用于存储过程
有几个面试常用的问题:
1 Statement与PreparedStatement的区别? 2 为什么要用PreparedStatement? 3 使用PreparedStatement有什么样的优势? 4 PreparedStatement又是如何避免SQL注入攻击的?
4.1 Statement与PreparedStatement的区别
前面已经提过,Statement执行通用化查询,PreparedStatement执行参数化查询。
1 conn.createStatement(); 2 conn.prepareStatement(sql);
4.2 用PreparedStatement的优势
使用PreparedStatement,数据库系统会对sql语句进行预编译处理(如果JDBC驱动支持的话),预处理语句将被预先编译好,这条预编译的sql查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。
同时,它还可以防止SQL注入式攻击。
4.3 PreparedStatement如何避免SQL注入攻击
在SQL注入攻击里,恶意用户通过SQL元数据绑定输入,比如:某个网站的登录验证SQL查询代码为:
strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"
恶意填入:
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";
那么sql语句就变成了:
strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"
即:(因此可以无账号密码直接登录。)
strSQL = "SELECT * FROM users;"
然而使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。
4.4 PreparedStatement的局限
为了防止SQL注入攻击,PreparedStatement不允许一个占位符(?)有多个值,在执行有**IN**子句查询的时候这个问题变得棘手起来。下面这个SQL查询使用PreparedStatement就不会返回任何结果:
SELECT * FROM loan WHERE loan_type IN (?)
preparedSatement.setString(1, "'personal loan', 'home loan', 'gold loan'");
如何解决呢?作者写在下篇博客里???下篇博客在哪???
4.5 PreparedStatement总结
当然可以使用Statement对象用来做做测试。但是在生产环境下一定要考虑使用 PreparedStatement 。
1. PreparedStatement可以写参数化查询,比Statement能获得更好的性能。
2. 对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,这种预处理语句查询比普通的查询运行速度更快。
3. PreparedStatement可以阻止常见的SQL注入式攻击。
4. PreparedStatement可以写动态查询语句
5. “?” 叫做占位符。
7. PreparedStatement查询默认返回FORWARD_ONLY的ResultSet,你只能往一个方向移动结果集的游标。当然你还可以设定为其他类型的值如:”CONCUR_READ_ONLY”。
8. 不支持预编译SQL查询的JDBC驱动,在调用connection.prepareStatement(sql)的时候,它不会把SQL查询语句发送给数据库做预处理,
而是等到执行查询动作的时候(调用executeQuery()方法时)才把查询语句发送个数据库,这种情况和使用Statement是一样的。
9. 占位符的索引位置从1开始而不是0,如果填入0会导致*java.sql.SQLException invalid column index*异常。
所以如果PreparedStatement有两个占位符,那么第一个参数的索引时1,第二个参数的索引是2.