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提供了 StatementPreparedStatement 和 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.

 

posted @ 2017-06-27 16:11  七月流火嗞嗞嗞  阅读(323)  评论(0编辑  收藏  举报