jdbc基础知识
JDBC(Java Database connectivity)
數據庫連接步驟:
1.加載數據庫驅動
將驅動所需要的jar包加入到工程的project build path中
加載數據庫驅動
Class.forName("com.mysql.jdbc.Driver");
要記住驅動連接的格式:
DRIVER = "com.mysql.jdbc.Driver";
記憶的時候可以聯想一下這個驅動字符串是域名的導致,也就是說域名應該是Driver.jdbc.mysql.com
在加載這個數據庫驅動的時候會跑出ClassNotFoundException這個異常
2.獲得數據庫連接
Connection conn = DrivrerManager.getConnection
("jdbc:mysql://localhost:3306/dbname","username","password";
jdbc:mysql://localhost:3306/dbname為連接字符串URL
URL也可以這么寫
URL = "jdbc:mysql://ipaddress:3306/dbname";
這個代表連接到主機IP地址為ipaddress的3306端口的dbname數據庫
當連接本地主機的默認3306端口號的時候可以這么寫:
URL = "jdbc:mysql:///dbname"
3.執行sql語句
String sql = "";
Statement stat = conn.createStatement();
stat.executeUpdate(sql);
這條語句只能執行insert、update、delete語句,返回值類型為int,代表受影響的行數。
stat.executeQuery(sql);
這條語句執行select語句,返回類型為ResultSet類型,代表查詢到的結果集。
對于insert、update、delete語句,又是想要獲得結果集對象可以使用帶兩個參數的executeUpdate()方法,出入一個靜態的值Statement.RETURN_GENERATED_KEYS
這時可以使用getGenerateKeys()方法來獲得ResultSet結果集對象,通過rs.getInt(indexColumn)來獲得主鍵的值。有時候程序在執行insert、Update、delete語句時需要知道主鍵的值。
4.關閉資源
rs.close();
stat.close();
conn.close();
在2、3、4操作中會跑出異常,使用try...catch語句捕獲異常
這時候存在一種情況當sql拼寫錯誤的時候,在執行的時候會拋出異常,但是conn資源和stat資源已經建立,但是并沒有被干必掉,長此以往就會導致數據庫可用連接減少。因此在關閉的時候在try...catch...語句中的finally語句塊中執行要關閉資源的操作,在關閉資源的時候還要先判斷資源是否為null,當不是null的時候再關閉。并且關閉資源的順序應與建立資源的順序相反。
example:
try {
if(rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
在實際生產環境中是不會使用這種方式的,當使用這個方式進行insert語句的時候就得拼SQL,這種做法相當的痛苦,因此不適用這種方式,并且這種方式從安全角度講容易被SQL注入。
String sql = "SELECT id,username,PASSWORD,eanble,money FROM t_account WHERE
username = '"+name+"' AND PASSWORD = '"+pwd+"'";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
當知道用戶名的時候就可以使用這種方式在隨意輸入密碼的時候登錄賬戶。
并且當輸入用戶名時的掃描器是以readLine()這樣的方法讀入的時候,還可以在輸入任意用戶名的情況下瀏覽該網站的任何數據:
空格'or 1=1#
?
?
PreparedStatement:
因此在使用的時候出現了PreparedStatement,這個類是Statement的子類。
優點:
1.對SQL語句進行預編譯處理,執行速度快
2.防止SQL注入
3.代碼閱讀性提高
PreparedStatement stat = conn.PreparedStatement(sql);
由于是預編譯,需要在執行之前就將sql語句傳進去。并且stat的獲得方式不再是createStatement(),而是conn.PreparedStatement();
在sql語句中傳入的值使用 ? 來表示,
String sql = "insert into tablename value(字段1,字段2,字段3...) values(?,?,?...)";
在執行之前要給這些問號賦值
stat.setType(1,value1);
Stat.setType(2,value2);
stat.setType(3,value3);
Type為要傳入值的類型,1、2、3代表為第幾個問號賦值,value為字段值。
?
?
?
DAO(Data Access Object)數據訪問對象
每個DAO封裝了對一個實體類(entity)的CRUD操作。實體類跟數據庫中的表相對應,實體類的屬性相當于表中的字段,實體類的對象相當于表中的一條記錄。
因此在創建實體類的時候根據表中的字段創建實體類的屬性,根據表中的記錄來創建對象。
以面向對象的角度來進行數據庫的CRUD操作,創建一個實體類的DAO類,來對這個實體類進行CRUD操作。
有了DAO之后,就不允許在DAO以外的地方出現JDBC的程序。
?
?
?
DAO(Data Access Object)數據訪問對象
每個DAO封裝了對一個實體類(entity)的CRUD操作。實體類跟數據庫中的表相對應,實體類的屬性相當于表中的字段,實體類的對象相當于表中的一條記錄。
因此在創建實體類的時候根據表中的字段創建實體類的屬性,根據表中的記錄來創建對象。
以面向對象的角度來進行數據庫的CRUD操作,創建一個實體類的DAO類,來對這個實體類進行CRUD操作。
有了DAO之后,就不允許在DAO以外的地方出現JDBC的程序。
?
?
工具類DbHelp(寫幫助類或工具類一定要注意中立性,什么類和方法都可以直接調用),創建executeUpdate()方法,來執行insert、Update、delete操作。
將釋放資源和獲得數據庫連接寫成單獨的放在放在工具類中。
在創建executeQuery()方法的時候要傳入sql語句,及sql的參數,sql的參數使用不定項參數的形式Object... params,創建類型為Object類型的不定項參數代表可以穿進去任何類型的參數。在獲得結果集的時候為了保證工具類的中立性和通用性建立一個RowMapper的接口,所有的實現類都繼承該接口,然后實現接口中的rowMapper方法,來將結果集中的數據已Object的形式返回出來,在各自的實體類的DAO中強制類型轉換為對應的實體類對象。同理也可以查詢所有的實體類,方法名queryForList(),返回一個List集合,集合中的元素為對應表中的實體類對象。
?
內部類:
注意:
一個Java文件中可以有多個類,但是只能有一個類是public來修飾的,但是不推薦這樣寫,因為這樣在調用的時候不利于閱讀,當這樣寫的時候編譯器實際上會編譯出兩個class文件一個是public修飾的類,一個是沒有訪問修飾符修飾的類。
內部類:(在一個類的內部聲明的類成為內部類)
public class Outer {
private String name = "tom";
public void outerMethod() {
System.out.println(name);
System.out.println("outermethod");
}
public class Inner {
private String name = "jack";
public void innerMethod() {
System.out.println(name);
System.out.println(Outer.this.name);
System.out.println("innerMethod");
}
}
}
當內部類的訪問修飾符為private的時候,內部類只能在外部類的內部使用,使用外部類時不知道內部類的存在
內部類的訪問修飾符可以為public,每個類都有各自的屬性和方法。內部類的創建需要外部類對象來調用內部類的構造方法
內部類可以使用外部類中的私有實例變量
public class Outer {
private String name = "Tom";
public void hi() {
System.out.println("Hello,This is Outer Class");
}
public class Inner {
public void sayHello() {
System.out.println("Hello," + name);
}
}
}
可以在外部類中創建內部類的對象,并調用內部類的方法
public class Outer {
private String name = "Tom";
public void hi() {
Inner inner = new Inner();
inner.age = 20;
inner.sayHello();
}
private class Inner {
private int age = 10;
public void sayHello() {
System.out.println("Hello," + Outer.this.name + "\t" + age);
}
}
}
內部類可以直接調用外部類的方法,但是外部類不能直接調用內部類的方法
內部類的實例化
Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.innerMethod();
當內部類的訪問修飾符為private的時候,內部類對象的創建就只能在外部類的內部創建內部類對象。
靜態內部類(使用static來修飾的內部類)
public class Outer {
public void outerMethod() {
System.out.println("outerMethod");
}
public static class Inner {
System.out.println("innerMethod");
}
}
靜態內部類的創建不普通內部類的創建不太一樣,需要使用靜態的方式來創建靜態內部類對象。
在靜態內部類中,當內部類調用了外部類的使用static修飾的方法和屬性的時候,外部類不能調用內部類的方法,因為這樣會發生堆棧溢出,會造成死循環
Outer.Inner inner = new Outer.Inner();
inner.innerMethod();
靜態內部類使用外部類的實例變量直接調用外部類.實例變量(Outer.name)
public class Outer {
public static String name = "Tom";
public static void hi() {
System.out.println("xixi");
}
public static class Inner {
public String name = "Jerry";
public void say() {
Outer.hi();
System.out.println("Hello"+Outer.name);
System.out.println("Hi!" + name);
}
}
}
局部內部類(在外部類的內部聲明的內部類成為局部內部類)
public class Outer {
public void outerMethod() {
final String name = "tom";
class Inner {
private String name = "jack";
System.out.println("innerMethod");
}
}
}
局部內部類創建在這個方法中,作用范圍也在這個方法當中,因此在創建局部內部類的時候不需要添加public訪問修飾符
局部內部類不能使用訪問修飾符類修飾,這個類的作用訪問就在這個方法的內部。局部內部類的對象只能在外部類的方法中創建,并執行內部類的方法
創建的方法只在這個方法的內部使用,這個時候可以使用局部內部類
為什么要使用局部內部類?
1.解決一個復雜的問題,想創建一個類來輔助你的解決方案,但是又不希望這個類是公共可用的
2.在方法內部實現一個接口,并返回對其的引用
局部內部類的方法需要引用外部類的方法的參數的時候,外部類方法的參數也必須是final類型的
局部內部類使用局部變量時這個局部變量必須是final的
當使用方法的參數的時候,方法的參數必須使用final來修飾
匿名局部內部類(只有方法體,沒有類名的局部內部類成為局部內部類)
example one:
public interface Usb {
public void run();
}
public Usb getUsb() {
return new Usb(){
@Override
public void run() {
System.out.println("runing...");
}
};
}
example two:
public void method() {
Object obj = new Object(){
@Override
public String toString() {
return "hi";
}
};
System.out.println(obj);
}
匿名局部內部類的簡單框架
public class A {
public voie methodname() {
類或接口 對象 = new 類或接口(){
public type methodname() {
}
};
}
}
新建一個類或者通過new一個接口來創建一個類,這個類沒名字(不知道該起什么名字好),但是由方法和方法體。
匿名局部內部類的原型
public class A {
public voie methodname() {
類或接口 對象 = new 類或接口(){
{
//這個匿名局部內部類的構造
}
};
}
}
創建一個匿名局部內部類的最簡單方式,有匿名局部內部類,但是沒有自定義方法
example:
Thread thread = new Thread(){
run{
System.out.println("thread start");
}
};
tread.start();
Object object = new Object(){
toString(){
System.out.println("hehe");
}
};
System.out.println(object.toString());
ArrayList<String> list = new ArrayList<String>{
{
add("a;sldfja");
add("asdfasdf");
}
};
System.out.println(list.size());
內部類的了解如上。
?
轉載于:https://www.cnblogs.com/shininguang/p/4799622.html
總結
- 上一篇: hdu 5311 Hidden Stri
- 下一篇: cmd的rd命令简单解析