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