J什麼是JDBC
Java Database Connectivity java數據庫連接
- SUN公司提供的訪問數據庫規則、規範,由於數據庫種類較多,並且java語言使用比較廣泛,sun公司就提供了一種規範,讓其他的數據庫去實現底層的訪問規則。我們的java程序只要使用sun公司提供的jdbc驅動即可。
JDBC連接數據庫
package com.itheima.test; import java.sql.*; public class MainTest { public static void main (String[] args) throws ClassNotFoundException { Connection conn=null; Statement st=null; ResultSet rs=null; try { //1.註冊驅動 //靜態代碼塊----》類加載了就會執行:java.sql.DriverManager.registerDriver(new Driver()); //因此以下代碼,相當於註冊了兩次 //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forName("com.mysql.jdbc.Driver");//修改 //2.建立連接 參數一:協議+訪問的數據庫,參數二:用戶名,參數三:密碼 Connection conn= DriverManager.getConnection("jdbc:mysql://localhost/student", "root", "root"); //3.創建statement,跟數據庫打交道,一定需要這個對象 Statement st = conn.createStatement(); //4.執行查詢,得到結果集 String sql="select * from mystudent"; ResultSet rs=st.executeQuery(sql); //遍歷每一條記錄 while(rs.next()) { int id=rs.getInt("id"); String name=rs.getString("name"); int age=rs.getInt("age"); System.out.println("id="+id+"==name="+name+"==age="+age); } rs.close(); st.close(); conn.close(); }catch(SQLException e) { e.printStackTrace(); } } }
釋放資源改進:
另外建一個類,專門進行釋放工作:
public class JDBCutil { public static void release(Connection conn,Statement st,ResultSet rs) { closeRs(rs); closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs) { try { if(rs!=null) rs.close(); }catch(SQLException e) { e.printStackTrace(); }finally { rs=null; } } private static void closeSt(Statement st ) { try { if(st!=null) st.close(); }catch(SQLException e) { e.printStackTrace(); }finally { st=null; } } private static void closeConn(Connection conn) { try { if(conn!=null) conn.close(); }catch(SQLException e) { e.printStackTrace(); }finally { conn=null; } } }
使用JDBC使用步驟
- 註冊驅動
- 建立連接
- 創建statement
- 執行sql,得到ResultSet
- 遍歷結果集
- 釋放資源
JDBC工具類構件
- 資源釋放工作的整合
- 驅動防二次註冊
//靜態代碼塊----》類加載了就會執行:java.sql.DriverManager.registerDriver(new Driver()); //因此以下代碼,相當於註冊了兩次驅動 //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forName("com.mysql.jdbc.Driver");//修改
3.使用properties配置文件
一般情況下,我們不會在java類文件中寫
static String url=jdbc:mysql://localhost/student static String name=root static String password=root
而是將它們單獨寫在資源文件中然後在使用時讀取文件,這樣我們只需要更改資源文件信息即可,不需要找到源java文件
//jdbc.properties driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost/student name=root password=root //JDBCutil.java static String driverClass=null; static String url=null; static String name=null; static String password=null; static { try { //讀文件 //1.創建一個屬性配置對象 Properties properties=new Properties(); //InputStream is=new FileInputStream("jdbc.properties"); //使用類加載器讀取SRC底下的資源文件,後面在servlet 對應文件位於src目錄下 InputStream is =JDBCutil.class.getClassLoader().getSystemResourceAsStream("jdbc.properties"); //導入輸入流 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url= properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
步驟
- 在src底下聲明一個文件xxx.properties
- 在工具類裡面,使用靜態代碼塊,讀取屬性
使用單元測試代碼:
步驟
- 定義一個類,textxxx,裡面定義方法
- 添加junit 支持:右鍵工程》add Library》Junit》選擇版本
- 在方法上加上註解@Test,其實就是一個標記
@Test public void testQuery(){ ... }
- 將光標點在需要測試的方法名上,然後右鍵Run
- 如果光條是綠色,表示代碼運行沒有錯誤
意義
對於不想講測試內容寫在main函數里,可以新建一個方法,講測試代碼放入執行。
即可以測試任何方法的正確性
注:如果方法較多,我們可以批量Run,在outline窗口進行操作即可
java對數據庫的增刪改查
查詢:Query
public void textQuery() { Connection conn=null; Statement st=null; ResultSet rs=null; try { //查詢 //1.獲取連接對象 conn = JDBCUtil.getConn(); //2.根據連接對象,得到statement st = conn.createStatement(); //3.執行sql語句,返回resultset String sql = "select * from mystudent"; rs=st.executeQuery(sql); //4.遍歷結果集 while(rs.next()) { String sname=rs.getString("sname");; String sex=rs.getString("sex");; String specialty=rs.getString("specialty"); String grade=rs.getString("grade");; System.out.println(sname+" "+sex+" "+specialty+" "+grade); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } }
增添:insert
public void textInsert() { Connection conn=null; Statement st=null; //ResultSet rs=null; try { //查詢 //1.獲取連接對象 conn = JDBCUtil.getConn(); //2.根據連接對象,得到statement st = conn.createStatement(); //3.執行添加 String sql = "insert into mystudent values(6,'王明','男','計算機','大一')"; //影響的行數,如果大於0表名操作成功,否則則失敗 int result=st.executeUpdate(sql); if(result>0) { System.out.println("添加成功"); }else { System.out.println("添加失敗"); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { JDBCUtil.release(conn, st); } }
刪除:delete
String sql = "delete from mystudent where id=6"; //影響的行數,如果大於0表名操作成功,否則則失敗 int result=st.executeUpdate(sql); if(result>0) { System.out.println("刪除成功"); }else { System.out.println("刪除失敗"); }
更新:update
String sql = "update mystudent set grade='大二' where id=1"; //影響的行數,如果大於0表名操作成功,否則則失敗 int result=st.executeUpdate(sql); if(result>0) { System.out.println("更新成功"); }else { System.out.println("更新失敗"); }
JDBC Dao模式
- 新建一個dao的接口,裡面聲明數據庫訪問規則
- 新建一個dao的實現類,具體實現早前定義的規則
- 直接使用實現
package dao; /** * 定義操作數據庫的方法 * */ public interface UserDao { /** * 查詢所有 * */ void Query();//findAll; } ----------------------------------------------- package dao.impl; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.jupiter.api.Test; import dao.UserDao; import util.JDBCUtil; public class UserDaoImpl implements UserDao{ @Override @Test public void Query() { Connection conn=null; Statement st=null; ResultSet rs=null; try { //1.獲取連接對象 conn = JDBCUtil.getConn(); //2.創建Statement對象 st = conn.createStatement(); //3. String sql = "select * from myuser"; rs = st.executeQuery(sql); while(rs.next()) { int id=rs.getInt("id"); String username=rs.getString("username"); String password=rs.getString("password"); System.out.println("id="+id+" username="+username+" password="+password); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } } -------------------------------------------------------------------------------- package test; import org.junit.Test; import dao.UserDao; import dao.impl.UserDaoImpl; public class TestUserDaoImpl { @Test public void TestQuery() { UserDao dao=new UserDaoImpl();//接口引用對象 dao.Query(); } }
statement安全問題
statement的執行,其實是拼接sql語句,然後再一起執行。
//前面先拼接sql語句,如果變量裡面帶有了數據庫的關鍵字,那麼一併認為是關鍵字,不認為是普通的字符串 String sql = "select * from myuser where username='"+username+"' and password='"+password+"'"; rs = st.executeQuery(sql); if(rs.next()) { System.out.println("登錄成功"); }else { System.out.println("登錄失敗"); } public void TestLogin() { UserDao dao=new UserDaoImpl(); dao.login("admin", "10086'or'1=1"); // SELECT * FROM myuser WHERE username="admin" AND PASSWORD="10088" OR 1=1; }
PrepareStatement
該對象就是替換前面的statement對象(預先對sql語句執行語法校驗)
String sql="select * from myuser where username=? and password=?"; //?對應的內容,後面不管傳遞什麼進來,都把它看成是字符串 PreparedStatement ps = conn.prepareStatement(sql); //?對應的索引從1開始 ps.setString(1, username); ps.setString(2, password); rs=ps.executeQuery(); if(rs.next()) { System.out.println("登錄成功"); }else { System.out.println("登錄失敗"); }
statement 給preparedstatement參數不報錯因為preparedstatement是statement 的子類(體現了多態性)
總結
- JDBC入門
- 抽取工具類
- statement CRUD
- Dao模式
- PreparedStatement CRUD
預處理sql語句,解決上面statement出現的問題
- dao裡面聲明crud,以及登錄方法
登錄方法:成功後返回該用戶的所有信息
查詢:如果是findAll返回一個集合
增加&刪除&更新
返回影響的行數即可 int類型
關鍵字: e.printStackTrace ; 規則