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();
}
}
}
} |