JDBC和异常总结及常见使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC和异常总结及常见使用相关的知识,希望对你有一定的参考价值。


JDBC

-一、JDBC连接过程

01.注册驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

02.获取连接

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

      访问数据库的用户名或密码错误


异常总结

     

 1. 异常的处理顺序,一定是子类异常处理在前,父类异常处理在后

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

 try {
				
}finally{
	dao.closeConnection();
}

  4. 自定义异常

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  

  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("")

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项目):

自定义异常

public class InputNullException extends Exception {
	public InputNullException(String msg){
		super(msg);
	}
}

web层

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


业务逻辑层:

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

数据层:

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

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

本文出自 “秦斌的博客” 博客,谢绝转载!

以上是关于JDBC和异常总结及常见使用的主要内容,如果未能解决你的问题,请参考以下文章

Python异常及处理方法总结(21.4定期更新)

实验报告六及总结

第八周课程总结及实验报告

第八周总结和实验六

Java学习总结(十九)——JDBC操作数据库,预编译的使用,事务,常见的连接池

PG异常状态详解及故障总结