JDBC
-一、JDBC连接过程
01.注册驱动
1
|
Class.forName(
"oracle.jdbc.driver.OracleDriver"
);
|
02.获取连接
1
|
Connection
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@10.0.19.252:1521:orcl"
,
"itxy"
,
"itxy"
);
|
-二、JDBC 常用接口
JDBC : sun提供的访问数据库的规范
这套规范用于高速数据库厂商,通过何种方式访问他们的数据库
01.java.sql 接口 Connection
sun的JDBC是一套接口规范,没有提供实现 (JDBC的接口实现,只能由各个数据库厂商自己实现)
02.java.sql
接口 Statement 用于执行静态 SQL 语句并返回它所生成结果的对象。
java.sql
接口 PreparedStatement 表示预编译的 SQL 语句的对象。
注意:开发的时候首先 PreparedStatement
原因: 1. 预编译的 SQL 语句的对象运行速度快
2. 安全 (可以防止SQL注入攻击)
03.java.sql 接口 ResultSet
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet
对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next
方法将光标移动到下一行;因为该方法在 ResultSet
对象没有下一行时返回 false
,所以可以在 while
循环中使用它来迭代结果集。
默认的 ResultSet
对象不可更新,仅有一个向前移动的光标。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。
-三、JDBC使用常见异常
java.lang
类 Class<T>
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver2
数据库驱动未加载成功
java.sql.SQLException: The Network Adapter could not establish the connection
数据库连接串配置错误
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
访问数据库的用户名或密码错误
注:
JDBC 与
UPDATE 表名 SET 字段名1=表达式1, 字段名2=表达式2, ... WHERE 条件;
重点: 返回值,int (update语句影响的记录条数)
但是如果jdbc与insert就不用看返回值,如果有异常,则表示插入失败。
异常总结
1. 异常的处理顺序,一定是子类异常处理在前,父类异常处理在后
1
2
3
4
5
6
7
8
9
|
try
{
biz.deleteStudent(
"s002"
);
System.out.println(
"删除完毕!"
);
}
catch
(SQLIntegrityConstraintViolationException e) {
}
catch
(Exception e) {
e.printStackTrace();
System.out.println(
"系统异常,请检查"
);
}
|
2. 在三层架构中,每层都可能出现异常,但是只有UI层采用最终的异常显示的决定权。
其它层可以捕获异常,但是处理后需要再次抛出!
3. 非托管资源(不受GC管理的资源),一定要在finally中释放,放在资源泄漏;
不受GC管理的资源:如数据连接Connection , 必须要用close()方法释放
还有IO流的释放,也必须使用close()
1
2
3
4
5
|
try
{
}
finally
{
dao.closeConnection();
}
|
4. 自定义异常
1
2
3
4
5
6
|
public
class
HavaSonRecordsException
extends
Exception{
public
HavaSonRecordsException(String msg){
super
(msg);
}
}
|
5. java.lang 类 Throwable
直接已知子类:
Error, Exception
Error 是 Throwable 的子类,用于指示合理的应用程序不应该试图捕获的严重问题。
注意: Error无需用try catch
Error异常举例: 如内存越界、内存溢出
6. try catch 是可以嵌套使用的
7.只有try,没有catch
1
2
3
4
5
6
|
try
{
dao.updateStuState(
0
, sno);
}
finally
{
//释放IO流的句柄
System.out.println(
"io资源释放"
);
}
|
8. checked Exception 与 unChecked Exception(Runtime Exception)
checked Exception(特点:在编译期可以明确异常的可能发生的位置,而且必须要捕获它):
ClassNotFoundException
SQLException
Runtime Excepiton (编译期无法检查到这个异常,只有在程序运行期间才能知道):
NullExcepiton , 10/0 , format("")
1
2
3
|
public
class
InputNullExcepiton
extends
RuntimeException{}
//RuntimeException无需强制处理
public
class
InputNullExcepiton
extends
Exception{}
//自定义异常,建议extends Exception
|
//数据库Connection是一种宝贵的资源,很容易称为业务系统的性能瓶颈
使用原则:
晚打开,早关闭 ----- 使用时间越短越好
Connection尽量可以重用
//数据库Connection的数量不是无限的,它受限于硬件(CPU)
补:
java.util 类 Date //除了dao层之外,都尽量使用java.util.Date
java.sql 类 Date //只能在dao层使用
练习(Java项目):
自定义异常
1
2
3
4
5
|
public
class
InputNullException
extends
Exception {
public
InputNullException(String msg){
super
(msg);
}
}
|
web层
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
|
public
class
StuUI {
/**
* 删除学生
*/
public
static
void
deleteStuTest(){
StuBiz biz =
new
StuBiz();
try
{
biz.deleteStudent(
"s003234"
);
System.out.println(
"删除完毕!"
);
}
catch
(Exception e) {
e.printStackTrace();
System.out.println(
"系统异常,请检查"
);
}
}
/**
* 添加学生
*/
public
static
void
addStuTest(){
StuBiz biz =
new
StuBiz();
TStudent ts =
new
TStudent();
ts.setSname(
"jack"
);
ts.setSno(
"s002244"
);
ts.setCno(
"c0124"
);
ts.setSex(
"f"
);
ts.setAddress(
"taiyuan"
);
ts.setTel(
"155345263"
);
String s =
"2012-06-21"
;
SimpleDateFormat sdf =
new
SimpleDateFormat(
"yyyy-MM-dd"
);
java.util.Date d1 =
null
;
try
{
d1 = sdf.parse(s);
}
catch
(ParseException e1) {
e1.printStackTrace();
}
//先把字符串转为util.Date对象
java.sql.Date d2 =
new
java.sql.Date(d1.getTime());
ts.setBirthday(d2);
ts.setHeight(
54
);
ts.setState(
1
);
try
{
biz.addStu(ts);
System.out.println(
"添加学生成功!"
);
}
catch
(InputNullException e){
System.out.println(
"入参为空!"
);
}
catch
(Exception e) {
e.printStackTrace();
System.out.println(
"插入失败!"
);
}
}
/**
* 查询所有学生信息
*/
public
static
void
showStu(){
StuBiz biz =
new
StuBiz();
try
{
List<TStudent> stus = biz.findAllStu();
Iterator<TStudent> it = stus.iterator();
while
(it.hasNext()){
TStudent t = it.next();
System.out.println(t.getSname() +
"--"
+ t.getSno() +
"--"
+ t.getBirthday());
}
}
catch
(Exception e) {
e.printStackTrace();
System.out.println(
"查询失败!"
);
}
}
public
static
void
main(String[] args) {
StuUI.showStu();
}
}
|
业务逻辑层:
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
|
public
class
StuBiz {
/**
* 删除学生
* 注意: 1. 当学生没有产生业务数据时,直接删除物理记录
* 2. 当学生产生了业务数据时,只能做逻辑删除
* @param sno
* @throws Exception
*/
public
void
deleteStudent(String sno)
throws
Exception{
if
(sno !=
null
){
StuDao dao =
new
StuDao();
try
{
dao.deleteStudent(sno);
}
catch
(java.sql.SQLIntegrityConstraintViolationException e){
if
(e.getSQLState().equals(
"23000"
)){
//找到了子记录
try
{
dao.updateStuState(
0
, sno);
}
catch
(Exception e2) {
e2.printStackTrace();
throw
e2;
}
finally
{
dao.closeConnection();
}
}
}
catch
(Exception e) {
throw
e;
}
finally
{
dao.closeConnection();
}
}
else
{
throw
new
Exception(
"入参错误,sno=null"
);
}
}
/**
* 添加学生
* @param ts
* @throws Exception
*/
public
void
addStu(TStudent ts)
throws
Exception{
if
(ts!=
null
){
StuDao dao =
new
StuDao();
try
{
boolean
bet = dao.findClass(ts.getCno());
if
(!bet){
throw
new
Exception(
"班级不存在"
);
}
else
{
dao.addStu(ts);
}
}
catch
(Exception e) {
throw
e;
}
finally
{
dao.closeConnection();
}
}
else
{
throw
new
Exception(
"入参错误!"
);
}
}
/**
* 查询所有学生信息
* @return
* @throws Exception
*/
public
List<TStudent> findAllStu()
throws
Exception {
//注意:面向接口编程不能是实现类返回
List<TStudent> stus;
StuDao dao =
new
StuDao();
try
{
stus = dao.findAllStu();
}
catch
(Exception e) {
throw
e;
}
finally
{
dao.closeConnection();
}
return
stus;
}
}
|
数据层:
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
113
|
public
class
StuDao
extends
BaseDao{
/**
* 删除学生
* 注意: 1. 当学生没有产生业务数据时,直接删除物理记录
* 2. 当学生产生了业务数据时,只能做逻辑删除
* @param sno
* @throws Exception
*/
public
void
deleteStudent(String sno)
throws
Exception{
String sql =
"delete from tstudent where sno=?"
;
this
.openConnection();
PreparedStatement ps =
this
.conn.prepareStatement(sql);
ps.setString(
1
, sno);
ps.executeUpdate();
ps.close();
}
/**
* 修改学生的状态值
* @param state
* @throws Exception
*/
public
void
updateStuState(
int
state,String sno)
throws
Exception{
String sql =
"update tstudent set state=? where sno=?"
;
this
.openConnection();
PreparedStatement ps =
this
.conn.prepareStatement(sql);
ps.setInt(
1
, state);
ps.setString(
2
, sno);
ps.executeUpdate();
ps.close();
}
/**
* 添加学生
* @param ts
* @throws Exception
*/
public
void
addStu(TStudent ts)
throws
Exception {
String sql =
"insert into tstudent values(?,?,?,?,?,?,?,?,?)"
;
//数据库打开
this
.openConnection();
PreparedStatement ps =
this
.conn.prepareStatement(sql);
ps.setString(
1
, ts.getSname());
ps.setString(
2
, ts.getSno());
ps.setString(
3
, ts.getCno());
ps.setString(
4
, ts.getSex());
ps.setString(
5
, ts.getAddress());
ps.setString(
6
, ts.getTel());
ps.setDate(
7
, ts.getBirthday());
ps.setInt(
8
, ts.getHeight());
ps.setInt(
9
, ts.getState());
ps.executeUpdate();
ps.close();
}
/**
* 添加学生的时候,检查班级是否存在
* @param cno
* @return
* @throws Exception
*/
public
boolean
findClass(String cno)
throws
Exception {
boolean
bRet =
false
;
String sql =
"select * from tclass where cno=?"
;
this
.openConnection();
PreparedStatement ps =
this
.conn.prepareStatement(sql);
ps.setString(
1
, cno);
ResultSet rs = ps.executeQuery();
while
(rs.next()){
bRet =
true
;
}
rs.close();
ps.close();
return
bRet;
}
/**
* 查询所有学生信息
* @return
* @throws Exception
*/
public
List<TStudent> findAllStu()
throws
Exception {
List<TStudent> stuList;
//写成两行
String sql =
"select * from tstudent"
;
//写在openConnection之前
this
.openConnection();
PreparedStatement ps =
this
.conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
stuList =
new
ArrayList<TStudent>();
//这样如果前面有错就不用产生内存分配
while
(rs.next()){
TStudent ts =
new
TStudent();
//new TStudent()是新建一个内存,这个不会被释放掉,只不过每次会建立对象引用
ts.setSname(rs.getString(
"sname"
));
ts.setCno(rs.getString(
"cno"
));
ts.setSno(rs.getString(
"sno"
));
ts.setAddress(rs.getString(
"address"
));
ts.setSex(rs.getString(
"sex"
));
ts.setTel(rs.getString(
"tel"
));
ts.setBirthday(rs.getDate(
"birthday"
));
ts.setHeight(rs.getInt(
"height"
));
ts.setState(rs.getInt(
"state"
));
stuList.add(ts);
//集合里面放的是引用,向集合中添加,就是复制对象地址,然后释放这个对象地址
}
rs.close();
ps.close();
return
stuList;
}
}
|
basedao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public
class
BaseDao {
protected
Connection conn;
public
void
openConnection()
throws
Exception{
//通过反射技术,对oracel的驱动对象进行类的加载 (其实是在做类型检查)
//在类的加载时,会调用OracleDriver中的静态代码块和静态变量初始化
Class.forName(
"oracle.jdbc.driver.OracleDriver"
);
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@10.0.19.252:1521:orcl"
,
"itxy"
,
"itxy"
);
}
public
void
closeConnection() {
if
(
this
.conn !=
null
){
try
{
this
.conn.close();
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
}
|