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