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
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. 异常的处理顺序,一定是子类异常处理在前,父类异常处理在后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,没有catchtry {
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 stus = biz.findAllStu();
Iterator 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 findAllStu() throws Exception {
//注意:面向接口编程不能是实现类返回
List 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 findAllStu() throws Exception {
List stuList;//写成两行
String sql = "select * from tstudent";//写在openConnection之前
this.openConnection();
PreparedStatement ps = this.conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
stuList = new ArrayList();//这样如果前面有错就不用产生内存分配
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;
}
}
basedaopublic 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();
}
}
}
}