jdbc
java database connectivity,java數據庫連接,為了降低操作數據的難度,java提供jdbc,按照java面向對象特點,對操作進行了很多封裝。
jdbc提供了很多接口,然后不同數據庫廠商去實現這個接口,到底底層如何去實現,不同的數據庫不一樣,不同的數據庫廠商需要提供接口實現類(驅動類、驅動程序 driver、驅動)
我們連接不同的數據庫,我們只需要使用不同的驅動即可。
j:java:提供訪問數據庫的規范(接口),
dbc:接口的實現,廠商去實現這個接口。
jdbc是一種用于執行sql語句的java api.
版本號
1.1.1 major. minor. build
major:項目由架構、大規模的變化
minor:有新功能的時候
build:編譯版本
jdbc開發
java程序使用第三方提供工具框架,都需要導入jar包
可以通過以下網址搜索找到mysql的相關jar包
下載好jar包后,在于src同級的目錄下,建立一個lib文件夾,添加jar包,并添加依賴
代碼實現
通過一個簡單的案例來實現jdbc的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import java.sql.*; public class demo02 { public static void main(string[] args) throws classnotfoundexception, sqlexception { //1注冊驅動 class .forname( "com.mysql.jdbc.driver" ); //2建立連接 string url = "jdbc:mysql://localhost:3306/mydb01" ; string usernname = "xxx" ; //登錄數據庫的賬號 string password = "xxxx" ; //登錄數據庫的密碼 connection conn = drivermanager.getconnection(url, usernname, password); //3獲取執行sql語句的對象 statement statement = conn.createstatement(); //4獲取數據庫返回的結果 string sql = "delete from emp where empno = " + "7499" ; string sqlupdate = "update emp set sal = " + 10000 + " where empno = " + "7369" ; string sqlinsert = "insert into emp values( 2018 ,\"boss\",\"king\", null ,\" 2018 - 8 - 8 \ ",15000,10000,10);" ; //5處理數據集 int i = statement.executeupdate(sql); int s = statement.executeupdate(sqlupdate); int ins = statement.executeupdate(sqlinsert); system.out.println(i + "行受到影響----刪除" ); system.out.println(s + "行受到影響----更新" ); system.out.println(ins + "行受到影響----插入" ); //6關閉連接 statement.close(); conn.close(); } } |
使用jdbc的順序
- (1)注冊數據庫驅動
- (2)和數據庫建立連接
- (3)獲取執行sql語句的對象
- (4)獲取數據庫返回的結果
- (5)處理數據集(邏輯代碼)
- (6)釋放資源,關閉連接
常用類
connection
通過配置文件可以創建一個connect對象
statement
- 通過connect對象獲取操作數據庫的statement對象,
- 通過它來實現對數據庫增刪改查操作。
- executequery():查,返回數據集
- executeupdate():增刪改,返回int的數據,影響的行數
resultset
數據集,可以理解就是一個集合。
取出數據:
- 通過下標:從1開始
- 通過字段名:sql語句中select后面跟的字段,有可能和數據庫一樣,也可能不一樣
jdbc的優化
平時開發和項目上線之后使用的數據庫是不一樣的,不是同一個
這也就是我們說的,開發環境不一樣
開發環境不一樣,使用的數據庫也就不一樣,那么上面的數據庫中配置的三要素就要進行修改
而這種修改是人工操作的,人工操作就有存在了失誤,而修改之后的.java文件,也要重新編譯,這也可能出現錯誤
假設項目上線,需要以下四個步驟:
測試環境-->修改配置 -->重新編譯-->生產環境
如果想要避免上述出現的失誤的情況,就要繞開中間的兩個步驟
解決的方法就是,配置文件,添加配置文件,將要修改的配置信息存放到配置文件中,每次讀取信息從配置文件中讀取
而配置文件的位置是固定的,也不會重新編譯,這樣就可以降低風險
java中用io流也可以讀取配置文件,通過一個專有的類properties也可以讀寫配置文件
io讀取配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.sql.*; import java.util.properties; public class ioreadprop { public static void main(string[] args) throws classnotfoundexception, sqlexception, ioexception { //1注冊驅動 class .forname( "com.mysql.jdbc.driver" ); string[] para = read(); //2建立連接 string url = para[ 0 ]; string usernname = para[ 1 ]; string password = para[ 2 ]; connection conn = drivermanager.getconnection(url,usernname,password); //3獲取執行sql語句的對象 statement statement = conn.createstatement(); //4獲取數據庫返回的結果 string sql = "select * from emp" ; resultset resultset = statement.executequery(sql); //5處理數據集 try { while (resultset.next()){ //.getxxx方法中的參數 1,字段名 2.字段的下標 int empno = resultset.getint( "empno" ); string ename = resultset.getstring( "ename" ); string job = resultset.getstring( 3 ); date date = resultset.getdate( 5 ); system.out.println( "empno:" +empno+ ", ename:" +ename+ ", job:" +job+ ", date:" +date); } } catch (exception e){ e.printstacktrace(); } finally { //6關閉連接 resultset.close(); statement.close(); conn.close(); } } public static string [] read() throws ioexception { filereader fr = new filereader( "e:\\javalearning\\src\\jdbc\\jdbc.properties" ); //創建 寫入 緩沖區 bufferedreader bufferedreader = new bufferedreader( fr ); string [] str = new string[ 3 ]; for ( int i = 0 ;i < 3 ;i++){ str[i] = bufferedreader.readline().split( "=" )[ 1 ].replace( ";" , "" ).trim(); } bufferedreader.close(); fr.close(); return str; } } |
properties讀取配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
import java.io.*; import java.sql.*; import java.util.iterator; import java.util.properties; public class propreadprop { public static void main(string[] args) throws classnotfoundexception, sqlexception, ioexception { //1注冊驅動 class .forname( "com.mysql.jdbc.driver" ); //用戶數組存放數據庫信息 string[] para = new string[ 3 ]; //讀取配置文件 int i = 0 ; properties prop = new properties(); fileinputstream fileinputstream = new fileinputstream( "e:\\javalearning\\src\\jdbc\\jdbc.properties" ); inputstream in = new bufferedinputstream(fileinputstream); prop.load(in); iterator<string> it = prop.stringpropertynames().iterator(); while (it.hasnext()) { para[i] = prop.getproperty(it.next()); i++; } in.close(); //2建立連接 string url = para[ 0 ]; string usernname = para[ 1 ]; string password = para[ 2 ]; connection conn = drivermanager.getconnection(url, usernname, password); //3獲取執行sql語句的對象 statement statement = conn.createstatement(); //4獲取數據庫返回的結果 string sql = "select * from emp" ; resultset resultset = statement.executequery(sql); //5處理數據集 try { while (resultset.next()) { //.getxxx方法中的參數 1,字段名 2.字段的下標 int empno = resultset.getint( "empno" ); string ename = resultset.getstring( "ename" ); string job = resultset.getstring( 3 ); date date = resultset.getdate( 5 ); system.out.println( "empno:" + empno + ", ename:" + ename + ", job:" + job + ", date:" + date); } } catch (exception e) { e.printstacktrace(); } finally { //6關閉連接 resultset.close(); statement.close(); conn.close(); } } } |
分層dao
data access object數據訪問對象是一個面向對象的數據庫接口
會建立一個包:dao,里面的類都是用來操作數據庫的。
通常情況下,有幾張表,就有幾個dao
分層entity、bean、pojo
實體,也就是一個一個類,該類里面只有屬性,和對應set.get方法
往往一個表一個實體,實體的屬性和表的字段有沒有關系,名字一般一樣,類型相對應
使用逆向工程,通過表導出實體。
utils 工具類
代替我們去操作一系列的連接關閉等操作
案例:
目錄結構如下,
empdao代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package jdbc.dao; import jdbc.entity.emp; import jdbc.utils.jdbcutils; import java.sql.connection; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; public class empdao { /** * 根據員工id獲取員工信息 */ public emp getempbyid(integer id){ connection connection = null ; statement statement = null ; resultset rs = null ; emp emp = null ; try { connection = jdbcutils.getconnection(); statement = connection.createstatement(); rs = statement.executequery( "select * from emp where empno='" +id+ "'" ); while (rs.next()){ emp = new emp(); int empno = rs.getint( "empno" ); emp.setempno(empno); string ename = rs.getstring( "ename" ); emp.setename(ename); string job = rs.getstring( 3 ); emp.setjob(job); string hiredate = rs.getstring( 5 ); emp.sethiredate(hiredate); } } catch (sqlexception e) { e.printstacktrace(); } finally { jdbcutils.close(connection,statement,rs); } return emp; } public emp getempbyid(string id){ connection connection = null ; statement statement = null ; resultset rs = null ; emp emp = null ; try { connection = jdbcutils.getconnection(); statement = connection.createstatement(); rs = statement.executequery( "select * from emp where empno=" +id); while (rs.next()){ emp = new emp(); int empno = rs.getint( "empno" ); emp.setempno(empno); string ename = rs.getstring( "ename" ); emp.setename(ename); string job = rs.getstring( 3 ); emp.setjob(job); string hiredate = rs.getstring( 5 ); emp.sethiredate(hiredate); } } catch (sqlexception e) { e.printstacktrace(); } finally { jdbcutils.close(connection,statement,rs); } return emp; } } |
entity中的emp代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
package jdbc.entity; public class emp { //emp表中的相關屬性 private integer empno; private string ename; private string job; private string mgr; private string hiredate ; private double sal; private double comm; private integer deptno; public integer getempno() { return empno; } public void setempno(integer empno) { this .empno = empno; } public string getename() { return ename; } public void setename(string ename) { this .ename = ename; } public string getjob() { return job; } public void setjob(string job) { this .job = job; } public string getmgr() { return mgr; } public void setmgr(string mgr) { this .mgr = mgr; } public string gethiredate() { return hiredate; } public void sethiredate(string hiredate) { this .hiredate = hiredate; } public double getsal() { return sal; } public void setsal( double sal) { this .sal = sal; } public double getcomm() { return comm; } public void setcomm( double comm) { this .comm = comm; } public integer getdeptno() { return deptno; } public void setdeptno(integer deptno) { this .deptno = deptno; } //默認輸出方法 @override public string tostring() { return "emp{" + "empno=" + empno + ", ename='" + ename + '\ '' + ", job='" + job + '\ '' + ", mgr='" + mgr + '\ '' + ", hiredate='" + hiredate + '\ '' + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + '}' ; } } |
utils中的jdbcutils代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package jdbc.utils; import java.io.bufferedinputstream; import java.io.fileinputstream; import java.io.ioexception; import java.io.inputstream; import java.sql.*; import java.util.iterator; import java.util.properties; public class jdbcutils { private static final string url ; private static final string username ; private static final string password ; static { string [] parp = null ; try { parp = propread(); } catch (ioexception e) { e.printstacktrace(); } url = parp[ 0 ]; username = parp[ 1 ]; password=parp[ 2 ]; try { class .forname( "com.mysql.jdbc.driver" ); } catch (classnotfoundexception e) { e.printstacktrace(); } } /** * 創建連接 */ public static connection getconnection() throws sqlexception { connection conn = drivermanager.getconnection(url, username, password); return conn; } public static void close(connection co , statement state, resultset rs){ if (rs != null ){ try { rs.close(); } catch (sqlexception e) { e.printstacktrace(); } } if (state != null ){ try { state.close(); } catch (sqlexception e) { e.printstacktrace(); } } if (co != null ){ try { co.close(); } catch (sqlexception e) { e.printstacktrace(); } } } public static void close(connection co , statement state){ if (state != null ){ try { state.close(); } catch (sqlexception e) { e.printstacktrace(); } } if (co != null ){ try { co.close(); } catch (sqlexception e) { e.printstacktrace(); } } } /** * 讀取配置文件 * @return * @throws ioexception */ public static string [] propread() throws ioexception { string[] para = new string[ 3 ]; int i = 0 ; properties prop = new properties(); fileinputstream fileinputstream = new fileinputstream( "e:\\javalearning\\src\\jdbc\\jdbc.properties" ); inputstream in = new bufferedinputstream(fileinputstream); prop.load(in); iterator<string> it = prop.stringpropertynames().iterator(); while (it.hasnext()) { para[i] = prop.getproperty(it.next()); i++; } in.close(); return para; } } |
測試代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package jdbc; import jdbc.dao.empdao; import jdbc.entity.emp; import java.util.scanner; public class main { public static void main(string[] args) { empdao empdao = new empdao(); system.out.println( "請輸入id" ); scanner scanner = new scanner( system.in ); string value = scanner.nextline(); emp emp = empdao.getempbyid (value); emp emp1 = empdao.getempbyid ( 7900 ); system.out.println(emp); system.out.println(emp1); } } |
這樣就簡單實現了一個分層的使用jdbc的案例
sql注入攻擊
根據上述案例,我們可以輸入一個員工的id來查找該員工
但是有一個問題,你如何去規定用戶的輸入,下面給大家看一個現象
我的數據庫在中并沒有123456789這個id的人,那么為什么還會有結果呢?
就是因為我們的sql語句是根據字符串拼接生成的,當你輸入的數據中包含sql關鍵字時,會被當成sql語句去執行
注意:這是很危險的!
不友好的用戶可以根據這個漏洞對你的數據庫進行修改,甚至刪除你的數據庫!
解決方法:preparedstatement類
preparedstatement是statement的子類
解決原理:
sql語句不在拼接,而是通過預處理,也就是說,用戶輸入的任何內容,都只能作為值,不解析特殊字符。
修改之后打代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public emp getempbyid2(string id){ connection connection = null ; preparedstatement statement = null ; resultset rs = null ; emp emp = null ; try { connection = jdbcutils.getconnection(); string sql = "select * from emp where empno=?" ; statement = connection.preparestatement(sql); statement.setstring( 1 ,id); rs = statement.executequery(); while (rs.next()){ emp = new emp(); int empno = rs.getint( "empno" ); emp.setempno(empno); string ename = rs.getstring( "ename" ); emp.setename(ename); string job = rs.getstring( 3 ); emp.setjob(job); string hiredate = rs.getstring( 5 ); emp.sethiredate(hiredate); } } catch (sqlexception e) { e.printstacktrace(); } finally { jdbcutils.close(connection,statement,rs); } return emp; } |
再次測試:結果如圖
總結:并不是意味著statement不能用,或者不能sql拼接
但是如果是前端穿過的來的值需要直接放到sql語句中,就需要注意。
以上所述是小編給大家介紹的java基礎知識——jdbc詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:https://blog.csdn.net/h1025372645/article/details/89191301