這是本人在學(xué)習(xí)JDBC時所做的筆記,以初學(xué)者的角度切入,有需要的小伙伴可以看看矩欠。
GitHub地址
一、概述
JDBC:java database connectivity悠夯,SUN公司提供的一套操作數(shù)據(jù)庫的標準規(guī)范癌淮。
JDBC與數(shù)據(jù)庫驅(qū)動的關(guān)系:接口與實現(xiàn)的關(guān)系。數(shù)據(jù)庫驅(qū)動由數(shù)據(jù)庫廠商提供沦补,一般我們引用其jar文件即可乳蓄。
JDBC規(guī)范:
- DriverManager,用于注冊驅(qū)動
- Connection策彤,表示與數(shù)據(jù)庫創(chuàng)建的連接
- Statement:栓袖,操作數(shù)據(jù)庫sql語句的對象
- ResultSet,結(jié)果集或一張?zhí)摂M表
二店诗、JDBC程序?qū)崿F(xiàn)
- 注冊驅(qū)動
- 創(chuàng)建連接
- 得到執(zhí)行sql語句的Statement對象
- 執(zhí)行sql語句裹刮,并返回結(jié)果
- 處理結(jié)果
- 關(guān)閉資源
核心代碼在try語句塊里面,很少庞瘸,其余都是處理異常和關(guān)閉資源的捧弃。
String url = "jdbc:mysql://localhost:3306/mydb";
String sql = "SELECT * FROM student";
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
DriverManager.registerDriver(new Driver());
connection = DriverManager.getConnection(url, "root", "root");
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getInt("stuid"));
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("sex"));
System.out.println("-------------------------");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
三、JDBC常用類和接口
1擦囊、java.sql.DriverManager類
1.1违霞、注冊驅(qū)動
DriverManager.registerDriver(new Driver());
其實上述方式是不建議使用的,原因如下:
- 驅(qū)動會被注冊兩次
- 強烈依賴數(shù)據(jù)庫驅(qū)動的jar文件瞬场,耦合性高
對原因一做一下說明:
// Register ourselves with the DriverManager
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
上述代碼來自于com.mysql.jdbc.Driver买鸽,可見其自身也注冊了一次。
推薦用法:
Class.forName("com.mysql.jdbc.Driver");
1.2贯被、與數(shù)據(jù)庫建立連接
有三種方式眼五,常用方式一:
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password","root");
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb",info);
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?user=root&password=root");
其中第一個參數(shù)為url妆艘,是sun公司與數(shù)據(jù)庫廠商之間的協(xié)議:
jdbc:mysql://localhost:3306/mydb
協(xié)議 子協(xié)議 IP :端口號 數(shù)據(jù)庫
默認連接本機:jdbc:mysql:///mydb
2、java.sql.Connection接口
作用:創(chuàng)建執(zhí)行sql語句的對象:
Statement statement = connection.createStatement();
3看幼、java.sql.Statement接口
作用:執(zhí)行sql語句并返回結(jié)果:
- ResultSet executeQuery(String sql) 根據(jù)查詢語句返回結(jié)果集批旺,只能執(zhí)行select語句
- int executeUpdate(String sql) 根據(jù)執(zhí)行的DML(insert update delete)語句,返回受影響的行數(shù)
- boolean execute(String sql) 此方法可以執(zhí)行任意sql語句诵姜,返回boolean值汽煮,表示是否返回ResultSet結(jié)果集,僅當執(zhí)行select語句棚唆,且有返回結(jié)果時返回true, 其它語句都返回false暇赤,可以看出,返回值價值不大瑟俭,因此很少使用
提供一個游標翎卓,默認游標指向結(jié)果集第一行之前。
調(diào)用一次next()摆寄,游標向下移動一行。
提供一些get方法坯门。
封裝數(shù)據(jù)的方法:
/*根據(jù)序號取值微饥,索引從1開始*/
Object getObject(int columnIndex);
/*根據(jù)列名取值*/
Object getObject(String ColomnName);
我們經(jīng)常使用的是get某種具體類型的方法,比如:
getInt(int colIndex)
getInt(String colLabel)
Java的數(shù)據(jù)類型與數(shù)據(jù)庫中的類型的關(guān)系:
Java | 數(shù)據(jù)庫 |
---|---|
byte | tityint |
short | smallint |
int | int |
long | bigint |
double | double |
String | char,varchar |
Date | date |
四古戴、sql注入
sql注入是指通過特殊的輸入語句欠橘,讓應(yīng)用運行輸入者想要執(zhí)行的sql語句。
比如一個登錄的sql现恼,可能如下:
select * from user where name='root' and password='root'
name和password都是用戶輸入的肃续,常見的有如下注入方式:
- 知道存在的用戶名,name輸入
root' --
叉袍,這樣就把之后的條件都屏蔽了 - 用戶名隨意輸入始锚,password輸入
anything' OR 'x'='x
,這樣條件永遠成立
解決方法:
棄用Statement喳逛,改為其子類PreparedStatement瞧捌,另一方面,其效率也更高润文。
核心代碼:
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, "root", "root");
statement = connection.prepareStatement(sql);
statement.setString(1, "白子畫");
resultSet = statement.executeQuery();
當然姐呐,關(guān)于防止sql注入遠遠不止更換一個類這么單一,這里僅僅是拋磚引玉啦典蝌。