JDBC入門與簡單使用
前面介紹過資料庫的建立,與SQL語句的增刪改查,但是Java是如何連線資料庫的呢?當然是我們的JDBC了,本篇總結了Java通過JDBC連線資料庫的基本寫法。這裡不細講JDBC的原理,記住,JDBC操作的不是資料庫,而是資料庫的驅動,至於不同驅動由不同的資料庫的廠商提供。
匯入驅動jar包並且註冊驅動
匯入驅動
在工程下新建lib目錄,然後將mysql-connector-java-5.1.37-bin.jar驅動jar包匯入,然後新增到build path即可。
註冊驅動
核心程式碼
Class.forName("com.mysql.jdbc.Driver");
JDBC規範定義驅動介面:java.sql.Driver,MySql驅動包提供了實現類:com.mysql.jdbc.Driver
DriverManager工具類,提供註冊驅動的方法 registerDriver(),方法的引數是java.sql.Driver,所以我們可以通過如下語句進行註冊:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
以上程式碼不推薦使用,存在兩方面不足
- 硬編碼,後期不易於程式擴充套件和維護
- 驅動被註冊兩次。
通常開發我們使用Class.forName() 載入一個使用字串描述的驅動類。
如果使用Class.forName()將類載入到記憶體,該類的靜態程式碼將自動執行。
通過查詢com.mysql.jdbc.Driver原始碼,我們發現Driver類“主動”將自己進行註冊
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
……
}
連線資料庫
核心程式碼
Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);
獲取連線需要方法 DriverManager.getConnection(url,username,password),三個引數分別表示,url 需要連線資料庫的位置(網址) user使用者名稱 password 密碼
url比較複雜,下面是mysql的url:
JDBC規定url的格式由三部分組成,每個部分中間使用冒號分隔。
第一部分是jdbc,這是固定的;
第二部分是資料庫名稱,那麼連線mysql資料庫,第二部分當然是mysql了;
第三部分是由資料庫廠商規定的,我們需要了解每個資料庫廠商的要求,mysql的第三部分分別由資料庫伺服器的IP地址(localhost)、埠號(3306),以及DATABASE名稱(mydb)組成。
獲取可執行SQL語句的物件
String sql = "某SQL語句";
Statement stmt = con.createStatement();
常用方法:
int executeUpdate(String sql); --執行insert update delete語句.
ResultSet executeQuery(String sql); --執行select語句.
boolean execute(String sql); --執行select返回true 執行其他的語句返回false.
處理結果集(執行insert、update、delete無需處理)
ResultSet實際上就是一張二維的表格,我們可以呼叫其boolean next()方法指向某行記錄,當第一次呼叫next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的資料:
rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的資料
常用方法:
- Object getObject(int index) / Object getObject(String name) 獲得任意物件
- String getString(int index) / Object getObject(String name) 獲得字串
- int getInt(int index) / Object getObject(String name) 獲得整形
- double getDouble(int index) / Object getObject(String name) 獲得雙精度浮點型
釋放資源
與IO流一樣,使用後的東西都需要關閉!關閉的順序是先得到的後關閉,後得到的先關閉。
rs.close();
stmt.close();
con.close();
如何解決SQL語句注入問題
什麼注入問題
假設有登入案例SQL語句如下:
SELECT * FROM 使用者表 WHERE NAME = 使用者輸入的使用者名稱 AND PASSWORD = 使用者輸的密碼;
此時,當使用者輸入正確的賬號與密碼後,查詢到了資訊則讓使用者登入。但是當使用者輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的程式碼變為:
SELECT * FROM 使用者表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此時,上述查詢語句時永遠可以查詢出結果的。那麼使用者就直接登入成功了,顯然我們不希望看到這樣的結果,這便是SQL隱碼攻擊問題。
為此,我們使用PreparedStatement來解決對應的問題。
如何解決
使用PreparedStatement預處理物件時,建議每條sql語句所有的實際引數,都使用逗號分隔。
String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement預處理物件程式碼:
PreparedStatement psmt = conn.prepareStatement(sql)
常用方法:
- 執行SQL語句:
- int executeUpdate(); --執行insert update delete語句.
- ResultSet executeQuery(); --執行select語句.
- boolean execute(); --執行select返回true 執行其他的語句返回false.
- 設定實際引數
- void setXxx(int index, Xxx xx) 將指定引數設定為給定Java的xx值。在將此值傳送到資料庫時,驅動程式將它轉換成一個 SQL Xxx型別值。
例如: - setString(2, "家用電器") 把SQL語句中第2個位置的佔位符? 替換成實際引數 "家用電器"
詳解預處理物件executeUpdate方法
通過預處理物件的executeUpdate方法,完成記錄的insert\update\delete語句的執行。操作格式統一如下:
1. 註冊驅動
2. 獲取連線
3. 獲取預處理物件
4. SQL語句佔位符設定實際引數
5. 執行SQL語句
6. 釋放資源
插入記錄:insert
實現向分類表中插入指定的新分類
public void demo01() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理物件
String sql = "insert into sort(sname) values(?)";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句佔位符設定實際引數
stat.setString(1, "奢侈品");
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("新新增記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
更新記錄:update
實現更新分類表中指定分類ID所對應記錄的分類名稱
public void demo02() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理物件中
String sql = "update sort set sname=? where sid=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句佔位符設定實際引數
stat.setString(1, "數碼產品");
stat.setInt(2, 1);
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("更新記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
刪除記錄:delete
實現刪除分類表中指定分類ID的記錄
public void demo03() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理物件
String sql = "delete from sort where sid=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句佔位符設定實際引數
stat.setInt(1, 1);
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("刪除記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
詳解預處理物件executeQuery方法
通過預處理物件的executeQuery方法,完成記錄的select語句的執行。操作格式統一如下:
1. 註冊驅動
2. 獲取連線
3. 獲取預處理物件
4. SQL語句佔位符設定實際引數
5. 執行SQL語句
6. 處理結果集(遍歷結果集合)
7. 釋放資源
查詢記錄:select
- 實現查詢分類表所有記錄
public void demo04() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理物件
String sql = "select * from sort";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句佔位符設定實際引數
// 5執行SQL語句
ResultSet rs = stat.executeQuery();
// 6處理結果集(遍歷結果集合)
while( rs.next() ){
//獲取當前行的分類ID
String sid = rs.getString("sid");//方法引數為資料庫表中的列名
//獲取當前行的分類名稱
String sname = rs.getString("sname");
//顯示資料
System.out.println(sid+"-----"+sname);
}
// 7釋放資源
rs.close();
stat.close();
conn.close();
}
- 實現查詢分類表中指定分類名稱的記錄
public void demo05() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理物件
String sql = "select * from sort where sname=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句佔位符設定實際引數
stat.setString(1, "奢侈品");
// 5執行SQL語句
ResultSet rs = stat.executeQuery();
// 6處理結果集(遍歷結果集合)
while( rs.next() ){
//獲取當前行的分類ID
String sid = rs.getString("sid");//方法引數為資料庫表中的列名
//獲取當前行的分類名稱
String sname = rs.getString("sname");
//顯示資料
System.out.println(sid+"-----"+sname);
}
// 7釋放資源
rs.close();
stat.close();
conn.close();
}
JDBC程式碼優化
上面發現有許多重複的程式碼,所以可以將注入連線操作進行封裝,並且可以將一些配置寫入一個配置檔案中。
JDBC工具類
“獲得資料庫連線”操作,將在以後的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連線物件的方法,從而達到程式碼的重複利用。
該工具類提供方法:public static Connection getConn ()。程式碼如下:
public class JDBCUtils {
public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/mydb";
public static final String USER = "root";
public static final String PASSWORD = "root";
static {
try {
Class.forName(DRIVERNAME);
} catch (ClassNotFoundException e) {
System.out.println("資料庫驅動註冊失敗!");
}
}
//提供獲取連線的方法
public static Connection getConn() throws Exception {
// 2. 獲得連線
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
// 返回連線
return conn;
}
}
properties配置檔案
- 使用properties配置檔案
開發中獲得連線的4個引數(驅動、URL、使用者名稱、密碼)通常都存在配置檔案中,方便後期維護,程式如果需要更換資料庫,只需要修改配置檔案即可。
通常情況下,我們習慣使用properties檔案,此檔案我們將做如下要求:
- 檔案位置:任意,建議src下
- 檔名稱:任意,副檔名為properties
- 檔案內容:一行一組資料,格式是“key=value”.
key命名自定義,如果是多個單詞,習慣使用點分隔。例如:jdbc.driver
value值不支援中文,如果需要使用非英文字元,將進行unicode轉換。
- 建立配置檔案
在專案跟目錄下,建立檔案,輸入“db.properties”檔名。
檔案中的內容
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
user=root
password=root
- 載入配置檔案:Properties物件
對應properties檔案處理,開發中也使用Properties物件進行。我們將採用載入properties檔案獲得流,然後使用Properties物件進行處理。
JDBCUtils.java中編寫程式碼
public class JDBCUtils {
private static String driver;
private static String url;
private static String user;
private static String password;
// 靜態程式碼塊
static {
try {
// 1 使用Properties處理流
// 使用load()方法載入指定的流
Properties props = new Properties();
Reader is = new FileReader("db.properties");
props.load(is);
// 2 使用getProperty(key),通過key獲得需要的值,
driver = props.getProperty("driver");
url = props.getProperty("url");
user = props.getProperty("user");
password = props.getProperty("password");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 獲得連線
*/
public static Connection getConnection() {
try {
// 1 註冊驅動
Class.forName(driver);
// 2 獲得連線
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
使用JDBCUtils工具類
測試程式碼:
public class Demo {
@Test
public void insert(){
try{
//1,獲取連線物件
Connection conn = JDBCUtils.getConnection();
//2,指定要執行的SQL語句
String sql = "INSERT INTO zhangwu(name,money,parent) VALUES(?,?,?)";
//4,獲取SQL語句的執行物件 PreparedStatement
PreparedStatement ppstat = conn.prepareStatement(sql);
//5,執行SQL語句
ppstat.setString(1, "股票收入");
ppstat.setDouble(2, 5000);
ppstat.setString(3, "收入");
int line = ppstat.executeUpdate();
//6,處理結果集
System.out.println("line=" + line);
//7,關閉連線
ppstat.close();
conn.close();
} catch(SQLException e){
throw new RuntimeException(e);
}
}
}
相關文章
- SpringBoot2.x入門教程:引入jdbc模組與JdbcTemplate簡單使用Spring BootJDBC
- SpringMVC簡單搭建與入門SpringMVC
- spring Cloud Gateway 入門簡單使用SpringCloudGateway
- 【Webpack】1.入門及簡單使用Web
- Python - pydantic 入門介紹與 Models 的簡單使用Python
- Azkaban 簡單入門
- postgresql 簡單入門SQL
- SprintBoot簡單入門boot
- Vue簡單入門Vue
- Kafka簡單入門Kafka
- Mysql 簡單入門MySql
- git簡單入門Git
- Espresso 簡單入門Espresso
- Groovy 簡單入門
- Mysql入門【JDBC】MySqlJDBC
- Java Json API:Gson使用簡單入門JavaJSONAPI
- 小程式 – 簡單入門
- PWA超簡單入門
- SpringSecurity簡單入門SpringGse
- Quartz - Quartz簡單入門quartz
- AVFoundation 簡單入門二
- rxjs簡單入門JS
- canvas簡單入門(2)Canvas
- ViewModels 簡單入門View
- GitHub簡單入門教程Github
- akka入門-簡單示例
- Rust Rocket簡單入門Rust
- 21、jdbc入門1JDBC
- 22、jdbc入門2JDBC
- 24、jdbc入門3JDBC
- Selenium2(webdriver)入門之TestNG的安裝與簡單使用Web
- Sharding-JDBC 使用入門和基本配置JDBC
- opengl簡單入門例項
- 簡單入門Kubernetes
- Android 混淆簡單入門Android
- drools的簡單入門案例
- NoSLQ之MongoDB簡單入門MongoDB
- 入門Flink,很簡單