1、獲取連接
1) 把jar包復制到項目目錄下
2) 把jar包加入項目的buildpath環境變量中, 使得classpath也和buildpath一致, 讓類加載器便于加載具體子類
3) 反射加載驅動程序類, 會自動注冊驅動程序4) 通過驅動程序管理器獲取連接.
? ? ? ?在當前工程下創建jdbc.properties文件,其中內容如下(是連接Oracle、MySql數據庫所需要的四大參數分別是:加載驅動、獲取連接數據庫的IP及端口、用戶名,密碼),目的是方便調用和修改!
#driverClass?=?oracle.jdbc.driver.OracleDriver #url?=?jdbc:oracle:thin:@127.0.0.1:1521:orcl #user?=?scott#password?=?tigerdriverClass?=?com.mysql.jdbc.Driverurl?=?jdbc:mysql://127.0.0.1:3306/companyuser?=?root password?=?123456
獲取連接以及關閉連接的具體實現如下:
package?com.atguigu.jdbc; import?java.io.FileInputStream; import?java.sql.Connection; import?java.sql.Driver; import?java.sql.DriverManager; import?java.sql.SQLException; import?java.util.Properties; import?org.junit.Test; ?/** ?*?獲取連接 ?*?1)?把jar包復制到項目目錄下 ?*?2)?把jar包加入項目的buildpath環境變量中,?使得classpath也和buildpath一致,?讓類加載器便于加載具體子類 ?*?3)?反射加載驅動程序類,?會自動注冊驅動程序 ?*?4)?通過驅動程序管理器獲取連接. ?*?@author?Administrator ?* ?*/ public?class?DriverTest?{ //?使用Properties類對象的getPropety方法與FileInputStream方法獲取文件中的內容,從而創建Connection對象 @Test public?void?test5()?throws?Exception?{ Properties?properties?=?new?Properties(); properties.load(new?FileInputStream("jdbc.properties")); String?driverClass?=?properties.getProperty("driverClass"); String?url?=?properties.getProperty("url"); String?user?=?properties.getProperty("user"); String?password?=?properties.getProperty("password"); Class.forName(driverClass);?//?只需要加載類,?類的靜態語句塊就會被執行,?創建驅動程序對象,并把此對象注冊到驅動程序管理器中. Connection?connection?=?DriverManager.getConnection(url,?user,?password); System.out.println(connection); connection.close(); } }
鑒于每一次jdbc的操作都需要建立連接,我們將建立連接的方法、關閉資源的方法作為固定方法放在JdbcUtil類中,方便使用:
package?com.atguigu.jdbc; import?java.io.FileInputStream; import?java.io.IOException; import?java.sql.Connection; import?java.sql.DriverManager; import?java.sql.ResultSet; import?java.sql.SQLException; import?java.sql.Statement; import?java.util.Properties; public?class?JdbcUtil?{ //?獲取建立連接對象 public?static?Connection?getConnection()?throws?IOException,? ClassNotFoundException,? SQLException?{ Properties?properties?=?new?Properties(); properties.load(new?FileInputStream("jdbc.properties")); String?driverClass?=?properties.getProperty("driverClass"); String?url?=?properties.getProperty("url"); String?user?=?properties.getProperty("user"); String?password?=?properties.getProperty("password"); Class.forName(driverClass);?//?只需要加載類,?類的靜態語句塊就會被執行,?創建驅動程序對象,并把此對象注冊到驅動程序管理器中. Connection?connection?=?DriverManager.getConnection(url,?user,?password); return?connection; } //?關閉資源 public?static?void?close(Connection?connection)?{ close(connection,?null); } public?static?void?close(Connection?connection,?Statement?statement)?{ close(connection,?statement,?null); } public?static?void?close(Connection?connection,?Statement?statement,?ResultSet?resultSet)?{ if?(resultSet?!=?null)?{ try?{ resultSet.close(); }?catch?(Exception?e)?{ e.printStackTrace(); } } if?(statement?!=?null)?{ try?{ statement.close(); }?catch?(Exception?e)?{ e.printStackTrace(); } } if?(connection?!=?null)?{ try?{ connection.close(); }?catch?(Exception?e)?{ e.printStackTrace(); } } } }
Statement類
建立連接成功,現在進行與數據庫的交流,與數據庫交流需要使用到Statement類,首先我們需要建立一個User類以與Statement類中創建的在company數據庫中的的user表相對應:
package?com.atguigu.jdbc; public?class?User?{ private?String?user; private?String?password; public?User()?{ } public?User(String?user,?String?password)?{ super(); this.user?=?user; this.password?=?password; } public?String?getUser()?{ return?user; } public?void?setUser(String?user)?{ this.user?=?user; } public?String?getPassword()?{ return?password; } public?void?setPassword(String?password)?{ this.password?=?password; } @Override public?String?toString()?{ return?"User?[user="?+?user?+?",?password="?+?password?+?"]"; } }
使用Statement執行創建user表,并插入三行數據:
package?com.atguigu.jdbc; import?java.sql.Connection; import?java.sql.Statement; import?org.junit.Test; //?使用Statement執行創建user表,并插入三行數據 public?class?StatementTest?{ @Test public?void?test1()?{ Connection?connection?=?null; Statement?statement?=?null; try?{ connection?=?JdbcUtil.getConnection(); statement?=?connection.createStatement();//?獲取執行體對象 //?執行SQL //?創建user表 String?sql?=?"create?table?if?not?exists?user(user?varchar(50),?password?varchar(100))"; int?rows?=?statement.executeUpdate(sql);?//?執行的DDL語句,?還可以執行DML System.out.println(rows?+?"?rows?affected.."); rows?=?statement.executeUpdate("insert?into?user?values('admin','admin')"); System.out.println(rows?+?"?rows?affected.."); rows?=?statement.executeUpdate("insert?into?user?values('user1','user1')"); System.out.println(rows?+?"?rows?affected.."); rows?=?statement.executeUpdate("insert?into?user?values('user2','123456')"); System.out.println(rows?+?"?rows?affected.."); }?catch?(Exception?e)?{ e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?statement); } } }
然而Statement存在弊端:不僅需要拼寫sql語句,并且存在SQL注入的問題,具體問題在下面的小例子中體現
package?com.atguigu.jdbc; import?java.lang.reflect.Field; import?java.sql.Connection; import?java.sql.ResultSet; import?java.sql.ResultSetMetaData; import?java.util.Scanner; import?org.junit.Test; import?java.sql.Statement; public?class?TestStatement?{ //?弊端:需要拼寫sql語句,并且存在SQL注入的問題 @Test public?void?testLogin()?{ Scanner?scan?=?new?Scanner(System.in); System.out.print("用戶名:"); String?userName?=?scan.nextLine(); System.out.print("密???碼:"); String?password?=?scan.nextLine(); String?sql?=?"select?user,?password?from?user?where?user?=?'" +?userName?+?"'?and?password?=?'"?+?password?+?"'";? System.out.println(sql); User?user?=?get(sql,?User.class); if(user?!=?null){ System.out.println("登陸成功!"); }else{ System.out.println("用戶名或密碼錯誤!"); } } public?<t>?T?get(String?sql,?Class<t>?clazz)?{//?(sql,?Customer.class) T?t?=?null; Connection?conn?=?null; Statement?stam?=?null; ResultSet?rs?=?null; try?{ conn?=?JdbcUtil.getConnection(); stam?=?conn.createStatement(); rs?=?stam.executeQuery(sql); //?獲取結果集的元數據 ResultSetMetaData?rsmd?=?rs.getMetaData(); //?獲取結果集的列數 int?columnCount?=?rsmd.getColumnCount(); if?(rs.next())?{ t?=?clazz.newInstance(); for?(int?i?=?0;?i?<p><br>此程序我們需要使用正確的用戶名,和對應的密碼才能進入登陸成功,通過上面的程序我們可知用戶名和密碼分別是:</p> <p><span style="font-size:18px"><span style="font-weight:bold; white-space:pre"></span>+-------+----------+<br><span style="white-space:pre"></span>| user ?| password |<br><span style="white-space:pre"></span>+-------+----------+<br><span style="white-space:pre"></span>| admin | admin ? ?|<br><span style="white-space:pre"></span>| user1 | user1 ? ?|<br><span style="white-space:pre"></span>| user2 | 123456 ? |<br><span style="white-space:pre"></span>+-------+----------+</span></p> <p><span style="font-size:18px">正常情況下我們登陸情況如下圖:</span></p> <p><span style="font-size:18px"><strong><img src="https://img.php.cn/upload/article/000/000/194/741bd1e5a9daa53ca02355c05d4c803a-0.jpg" alt=""><br><br></strong></span></p> <p><span style="font-size:18px">但是SQL高手通過如下操作就能登陸成功,這就是SQL注入的問題</span></p> <p><span style="font-size:18px"><img src="https://img.php.cn/upload/article/000/000/194/a61a816a5f1463935f04eba093c308b1-1.jpg" alt=""><br></span></p> <h2><span style="font-size:18px"><strong>PreparedStatement類</strong></span></h2> <p><span style="font-size:18px"><strong>為了防止sql注入問題,于是我們需要使用他的子類PreparedStatement預編譯執行體,下面我們進行PreparedStatement的練習:</strong></span><br></p> <p><span style="font-size:18px">首先先創建Customer類<br>// 寫一個類Customer, 包含屬性name, gender, phone</span></p> <p><span style="font-size:18px"></span></p> <pre class="java">package?com.atguigu.jdbc; public?class?Customer?{ private?String?name; private?String?gender; private?String?phone; public?Customer(String?name,?int?age,?String?gender,?String?phone,)?{ super(); this.name?=?name; this.age?=?age; this.gender?=?gender; this.phone?=?phone; } public?Customer()?{ } public?String?getName()?{ return?name; } public?void?setName(String?name)?{ this.name?=?name; } public?String?getGender()?{ return?gender; } public?void?setGender(String?gender)?{ this.gender?=?gender; } public?String?getPhone()?{ return?phone; } public?void?setPhone(String?phone)?{ this.phone?=?phone; } @Override public?String?toString()?{ return?"Customer?[name="?+?name?+?",?gender="?+?gender?+?",?phone="?+?phone?+?"]"; } }
在測試類中使用PreparedStatment執行體對象創建相應的表, 并插入2條數據。
public?class?PreparedStatementTest?{ @Test public?void?exer1()?{ Connection?connection?=?null; PreparedStatement?preparedStatement?=?null; try?{ connection?=?JdbcUtil.getConnection(); String?sql?=?"create?table?if?not?exists?customer(name?varchar(30),?gender?enum('男','女')?default?'男',?phone?varchar(20))"; preparedStatement?=?connection.prepareStatement(sql); ? preparedStatement.executeUpdate(); JdbcUtil.close(null,?preparedStatement);?//?在獲取新的預編譯對象前,一定要先關閉原來的. String?sql2?=?"insert?into?customer(name,?gender,?phone)?values(?,??,??)"; preparedStatement?=?connection.prepareStatement(sql2);?//?要想重新執行新的SQL,必須再次預編譯 preparedStatement.setString(1,?"張三"); preparedStatement.setString(2,?"男"); preparedStatement.setString(3,?"13343493434"); int?rows?=?preparedStatement.executeUpdate(); System.out.println(rows?+?"?rows?affected."); preparedStatement.setString(1,?"李四"); preparedStatement.setString(2,?"女"); preparedStatement.setString(3,?"1322243434"); rows?=?preparedStatement.executeUpdate(); System.out.println(rows?+?"?rows?affected."); }?catch?(Exception?e)?{ e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?preparedStatement); } //?并通過客戶端驗證. } }
在Customer類中添加屬性int age,double weight,給Customer表中添加對應的列,并添加記錄
public?class?PreparedStatementTest?{ //?在Customer類中添加屬性int?age,double?weight,給Customer表中添加對應的列,并添加記錄 @Test public?void?test3()?{ Connection?connection?=?null; PreparedStatement?preparedStatement?=?null; try?{ connection?=?JdbcUtil.getConnection(); String?sql?=?"alter?table?customer?add?age?int?after?name"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.executeUpdate(); JdbcUtil.close(null,?preparedStatement); sql?=?"alter?table?customer?add?weight?double"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.executeUpdate(); JdbcUtil.close(null,?preparedStatement); sql?=?"insert?into?customer(name,?age,?gender,?phone,?weight)?values?(?,??,??,??,??)"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.setString(1,?"王五"); preparedStatement.setInt(2,?50); preparedStatement.setString(3,?"男"); preparedStatement.setString(4,?"134234234234"); preparedStatement.setDouble(5,?98.5); int?rows?=?preparedStatement.executeUpdate(); System.out.println(rows?+?"?rows?affected"); }?catch?(Exception?e)?{ //?TODO:?handle?exception e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?preparedStatement); } } //?添加記錄 @Test public?void?test4()?{ Connection?connection?=?null; PreparedStatement?preparedStatement?=?null; try?{ connection?=?JdbcUtil.getConnection(); String?sql?=?"alter?table?customer?add?birthdate?date"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.executeUpdate(); JdbcUtil.close(null,?preparedStatement); sql?=?"insert?into?customer(name,?age,?gender,?phone,?weight,?birthdate)?values?(?,??,??,??,??,??)"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.setString(1,?"趙六"); preparedStatement.setInt(2,?60); preparedStatement.setString(3,?"女"); preparedStatement.setString(4,?"13882342323"); preparedStatement.setDouble(5,?40); preparedStatement.setString(6,?"1960-2-3"); int?rows?=?preparedStatement.executeUpdate(); System.out.println(rows?+?"?rows?affected"); }?catch?(Exception?e)?{ //?TODO:?handle?exception e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?preparedStatement); } } //?再添加記錄 @Test public?void?test5()?{ Connection?connection?=?null; PreparedStatement?preparedStatement?=?null; try?{ connection?=?JdbcUtil.getConnection(); String?sql?=?"insert?into?customer(name,?age,?gender,?phone,?weight,?birthdate)?values?(?,??,??,??,??,??)"; preparedStatement?=?connection.prepareStatement(sql); preparedStatement.setObject(1,?"張七"); preparedStatement.setObject(2,?20); preparedStatement.setObject(3,?"女"); preparedStatement.setObject(4,?"1343434343"); preparedStatement.setObject(5,?58.8); preparedStatement.setObject(6,?"1980-3-8"); int?rows?=?preparedStatement.executeUpdate(); if?(rows?==?1)?{ System.out.println("插入成功"); } }?catch?(Exception?e)?{ //?TODO:?handle?exception e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?preparedStatement); } } }
像上面那樣添加每次重復同樣的代碼,我們這里設置通用的更新操作,并存入CommonUtil類中,作為工具類通用更新操作。具體實現如下:
package?com.atguigu.jdbc; import?java.io.FileNotFoundException; import?java.io.IOException; import?java.sql.Connection; import?java.sql.PreparedStatement; import?java.sql.SQLException; public?class?CommonUtil?{ /** ?*?通用更新操作 ?*?@param?sql?一個可以包含?的SQL語句 ?*?@param?values?SQL中有多少個?,可變參數就有多少個具體值 ?*?@return?更新以后影響的記錄數 ?*/ public?static?int?commonUpdate(String?sql,?Object...?values)?throws??FileNotFoundException,? ClassNotFoundException, IOException,? SQLException?{ Connection?connection?=?null; PreparedStatement?preparedStatement?=?null; try?{ connection?=?JdbcUtil.getConnection();?//?獲取連接 preparedStatement?=?connection.prepareStatement(sql);?//?把帶有?的SQL編譯 for?(int?i?=?0;?i?<h2><span style="font-size:18px"><span style="font-size:18px">ResultSet類</span></span></h2><p>至此我們實現了數據庫數據的建表,插入,更新,刪除,下面進行數據庫操作中比較難的查詢,需要使用到查詢結果集ResultSet類,循序漸進的練習實現如下:</p><p><span style="font-size:18px"></span></p><pre class="java">package?com.atguigu.jdbc; import?java.util.List; import?java.sql.Connection; import?java.sql.Date; import?java.sql.PreparedStatement; import?java.sql.ResultSet; import?java.sql.ResultSetMetaData; import?java.util.ArrayList; import?org.junit.Test; public?class?ResultSetTest?{ @Test public?void?test1()?{ //?select?*?from?customer;?結果如下 /* +------+------+--------+------------+--------+------------+ |?name?|?age??|?gender?|?phone??????|?weight?|?birthdate??| +------+------+--------+------------+--------+------------+ |?張七???????20?|?女?????????|?1343434343?|???58.8?|?1980-03-08?| |?張九???|????40?|?男????????|?1349932423?|???78.2?|?1977-08-08?| |?張三????|????3??|?女???????|?1332324234?|?????70?|?1979-08-08?| +------+------+--------+------------+--------+------------+ */ Connection?connection?=?null; PreparedStatement?prepareStatment?=?null; ResultSet?resultSet?=?null; try?{ connection?=?JdbcUtil.getConnection(); String?sql?=?"select?*?from?customer"; prepareStatment?=?connection.prepareStatement(sql); //?調用PreparedStatement對象的executeQuery方法產生ResultSet對象 resultSet?=?prepareStatment.executeQuery(); System.out.println(resultSet); while?(resultSet.next())?{?//?根據列的<span>序號</span>, 先檢測當前游標的下一行是否有數據,?如果有數據則移動游標,并返回true,?如果沒有數據,直接返回false String?name?=?resultSet.getString(1);?//?獲取到的是當前游標指向的行的第1列的值 int?age?=?resultSet.getInt(2);//?獲取到的是當前游標指向的行的第2列的值 String?gender?=?resultSet.getString(3);//?獲取到的是當前游標指向的行的第3列的值 String?phone?=?resultSet.getString(4);//?獲取到的是當前游標指向的行的第4列的值 double?weight?=?resultSet.getDouble(5);//?獲取到的是當前游標指向的行的第5列的值 Date?birthDate?=?resultSet.getDate(6);//?獲取到的是當前游標指向的行的第6列的值 System.out.println(name?+?"t"?+?age?+?"t"?+?gender?+?"t"?+?phone?+?"t"?+?weight?+?"t"?+?birthDate); } }?catch?(Exception?e)?{ e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?prepareStatment,?resultSet); } } //?我們改變查詢列名的順序進行查詢操作,使用下標不能實現了,我們需要根據虛表中的<span>列名</span> 進行查詢,并將查詢結果封裝成對象,添加到list集合中 @Test public?void?test2()?{ Connection?connection?=?null; PreparedStatement?prepareStatment?=?null; ResultSet?resultSet?=?null; try?{ connection?=?JdbcUtil.getConnection(); //?name?|?age??|?gender?|?phone??????|?weight?|?birthdate??| String?sql?=?"select?name?custName,?gender,?age,?weight,?phone,?birthdate?birth?from?customer"; prepareStatment?=?connection.prepareStatement(sql); resultSet?=?prepareStatment.executeQuery(); List<customer>?list?=?new?ArrayList<customer>(); //?基于虛表的結果集 while?(resultSet.next())?{ String?name?=?resultSet.getString("custName");//?獲取到的是當前游標指向的行的虛表中名字為name列的值 int?age?=?resultSet.getInt("age");//?獲取到的是當前游標指向的行的虛表中名字為age列的值 String?gender?=?resultSet.getString("gender");//?獲取到的是當前游標指向的行的虛表中名字為gender列的值 String?phone?=?resultSet.getString("phone"); double?weight?=?resultSet.getDouble("weight"); Date?birthDate?=?resultSet.getDate("birth"); Customer?customer?=?new?Customer(name,?age,?gender,?phone,?weight,?birthDate);?//?封裝成對象?O/R?mapping list.add(customer); } //?遍歷集合 for?(Customer?cust?:?list)?{ System.out.println(cust); } }?catch?(Exception?e)?{ e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?prepareStatment,?resultSet); } } //?我們改變查詢列名的順序進行查詢年齡大于任意數的操作,使用下標不能實現了,我們需要根據<span>虛表中的列名</span> 進行查詢,并將查詢結果封裝成對象,添加到list集合中 @Test public?void?test3()?{ Connection?connection?=?null; PreparedStatement?prepareStatment?=?null; ResultSet?resultSet?=?null; try?{ connection?=?JdbcUtil.getConnection(); //?name?|?age??|?gender?|?phone??????|?weight?|?birthdate??| String?sql?=?"select?name?custName,?gender,?age,?weight,?phone,?birthdate?birth?from?customer?where?age?>??"; prepareStatment?=?connection.prepareStatement(sql); prepareStatment.setObject(1,?20); resultSet?=?prepareStatment.executeQuery(); List<customer>?list?=?new?ArrayList<customer>(); //?<span>基于虛表的結果集</span> while?(resultSet.next())?{ String?name?=?resultSet.getString("custName");//?獲取到的是當前游標指向的行的 <span>虛表</span>中名字為name列的值 int?age?=?resultSet.getInt("age");//?獲取到的是當前游標指向的行的虛表中名字為age列的值 String?gender?=?resultSet.getString("gender");//?獲取到的是當前游標指向的行的虛表中名字為gender列的值 String?phone?=?resultSet.getString("phone"); double?weight?=?resultSet.getDouble("weight"); Date?birthDate?=?resultSet.getDate("birth"); Customer?customer?=?new?Customer(name,?age,?gender,?phone,?weight,?birthDate);?//?封裝成對象?O/R?mapping list.add(customer); } //?遍歷集合 for?(Customer?cust?:?list)?{ System.out.println(cust); } }?catch?(Exception?e)?{ e.printStackTrace(); }?finally?{ JdbcUtil.close(connection,?prepareStatment,?resultSet); } } //??獲取查詢結果,若查詢結果并沒有類與其對應,就需要獲取虛表的表結構進行查詢操作的打印輸出 @Test public?void?test4()?{ Connection?connection?=?null; PreparedStatement?prepareStatment?=?null; ResultSet?resultSet?=?null; try?{ connection?=?JdbcUtil.getConnection(); //?name?|?age??|?gender?|?phone??????|?weight?|?birthdate??| String?sql?=?"select?name?custName,?gender,?age,?weight,?phone,?birthdate?birth?from?customer"; prepareStatment?=?connection.prepareStatement(sql); resultSet?=?prepareStatment.executeQuery(); /* +----------+--------+------+--------+------------+------------+ |?custName?|?gender?|?age??|?weight?|?phone??????|?birth??????| +----------+--------+------+--------+------------+------------+ |?張七????? |?女???????????|???20?|???58.8?|?1343434343?|?1980-03-08?| |?張九????? |?男??????????|???40?|???78.2?|?1349932423?|?1977-08-08?| |?張三??? ????|?女??????????|???30??|?????70?|?1332324234?|?1979-08-08?| +----------+--------+------+--------+------------+------------+ */ ResultSetMetaData?metaData?=?resultSet.getMetaData();?//?獲取虛表的表結構對象 int?cols?=?metaData.getColumnCount();?//?獲取虛表共有多少列 //System.out.println(cols); String?colName?=?metaData.getColumnName(3);//?獲取基表的列名,?參數中的是第幾列 //System.out.println(colName); colName?=?metaData.getColumnName(6);//?獲取基表列名,?參數中的是第幾列 //System.out.println(colName); String?colLabel?=?metaData.getColumnLabel(6);?//?獲取虛表列名,?參數是第6列 //System.out.println(colLabel); System.out.println("---------------------------------"); for?(int?i?=?0;?i?<p><span style="font-size:18px"></span></p> <p>以上就是Jdbc--具體代碼實現的內容,更多相關內容請關注PHP中文網(www.php.cn)!</p> <p><span style="font-size:18px"><br><br></span><br></p> <p><span style="font-size:18px"><br><br><br></span></p> <p><span style="font-size:18px"><br><br></span></p> <p><span style="font-size:18px"><br><br></span></p> <p><br><br><br></p></customer></customer></customer></customer>