JDBC:Java DataBase Connection
本季目标
1、JDBC的分类
2、JDBC的主要操作类和接口: 
DriverManager、Connection、Statement、PreparedStatement、ResultSet
3、如何使用JDBC连接MySQL数据库
www.mldn.cn上有MYSQL的教程。
1、什么是JDBC? 
JDBC是JAVA提供的一个服务,专门用于访问数据库操作,而且注意:JDBC定义的是一个数据库访问的标准,所以里面基本上都是一系列的接口。各个数据库厂商如果要想支持JDBC操作,则肯定要提供一组相关的类,这些类肯定都是提供接口子类实现。
2、JDBC的分类 
·JDBC-ODBC桥连接 
·JDBC直接连接 
·JDBC网络连接
3、什么是ODBC? 
ODBC是微软公司定义的一个开放式数据库连接(Open DataBase Connection),使用ODBC可以连接各种数据库(前提:必须在windows中安装好驱动才可以)。在SUN 的JDK中默认提供了此数据库的驱动程序,所以JDK本身可以直接使用JDBC-ODBC进行访问。
访问的过程: 
JDBC --> ODBC --> 数据库 (性能比较低)
 
如果直接使用JDBC访问,访问过程:JDBC --> 数据库(性能较高)
4、主要操作接口 
· Connection:表示连接数据库的接口 
· Statement:表示操作数据库的接口(执行SQL语句) 
|- PreparedStatement:操作SQL语句,但是可以进行预处理操作。 
· ResultSet:表示查询之后的返回结果
5、使用JDBC-ODBC操作Access数据库
新建一个access空数据库
image
建立好了一个数据库,数据库的名字为:mydb.mdb
image
在数据库中创建表: 
建立一张person表,包括以下字段: 
· id --> 自动增长 
· name --> 姓名 
· age --> 年龄
image
因为我们的目的是使用JDBC-ODBC桥连接操作数据库,所以此处必须先配置ODBC数据源:管理工具 --> 数据源(ODBC)
image
配置一个全局的数据源名称
image
在ODBC上设置了一个数据库的别名,此别名testDB代表mydb.mdb。以后在操作的时候就是使用testDB即可。
image
如果要设置access数据源名称,则必须先关闭打开的access文件之后再设置
image
保存并关闭access数据库
image
image
那么以后直接使用testDB就可以访问数据库了。
1、操作数据库的步骤(JDBC) 
· 加载数据库的驱动程序:Class.forName("驱动程序") ; 
· 通过连接管理器,取得一个数据库的连接:DriverManager.getConnection(连接地址) 
· 通过连接创建数据库的操作对象:Statement 
· 操作数据库 --> 执行SQL语句 
· 关闭数据库操作
我们现在使用Eclipse新建一个JDBCProject项目来测试下哈~
image
在JDBC中所有的操作步骤都是一样,但是驱动程序和连接地址是不一样的,ODBC的: 
· 驱动程序:sun.jdbc.odbc.JdbcOdbcDriver 
· 连接地址:jdbc:odbc:ODBC配置的DSN名称(jdbc:odbc:testDB)
JDBC中的所有操作的包都是java.sql包中
JDBCDemo01:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo01 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                Statement stmt = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                String sql = "INSERT INTO person(name,age) VALUES ('Michael',20)";    
                try {    
                        stmt = conn.createStatement();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                try {    
                        stmt.executeUpdate(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        stmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    
}
验证一下,有没问题,没有报错,正常
image
现在看下access中数据有没写入进出哈~
image
现在所插入的数据都是固定死的,那么能不能插入一些灵活的数据呢?例如:有些数据可以直接从键盘上输入。
JDBCDemo02:
package com.redking.jdbc.demo;    
import java.io.BufferedReader;    
import java.io.IOException;    
import java.io.InputStreamReader;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo02 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                String name = null;    
                int age = 0;    
                BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));    
                System.out.println("请输入姓名:");    
                try {    
                        name = buf.readLine();    
                } catch (IOException e1) {    
                        e1.printStackTrace();    
                }    
                System.out.println("请输入年龄:");    
                try {    
                        age = Integer.parseInt(buf.readLine());    
                } catch (NumberFormatException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                } catch (IOException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                }    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                Statement stmt = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                String sql = "INSERT INTO person(name,age) VALUES ('"+name+"',"+age+")";    
                System.out.println(sql);    
                try {    
                        stmt = conn.createStatement();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                try {    
                        stmt.executeUpdate(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        stmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    
}
看下效果:
image
已经写入数据库了哈~
image
那能不能修改一条数据呢?
JDBCDemo03:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo03 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                Statement stmt = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                String sql = "UPDATE person SET name='51cto',age=25 WHERE id=4";    
                try {    
                        stmt = conn.createStatement();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                try {    
                        stmt.executeUpdate(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        stmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    

就改了一行代码,看下效果,有没改过来哈~
image
现在把ID为4的数据删除掉
JDBCDemo04:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo04 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                Statement stmt = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                String sql = "DELETE FROM person WHERE id=4";    
                try {    
                        stmt = conn.createStatement();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                try {    
                        stmt.executeUpdate(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        stmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    
}
看下效果,有没删除了哈~
image
注意: 
在插入的程序处实际上存在了一点问题: 
例如:现在要输入姓名为:Mr'Wang 
INSERT INTO person(name,age) VALUES ('Mr'Wang',30)
image 
一般来说在使用JDBC 操作数据库的时候,往往很少会去使用Statement 进行操作,而经常使用Statement的子接口PreparedStatement进行操作。 
PreparedStatement 是预处理,表示先在数据库中插入一条信息,但是信息的内容暂时不确定,等待用户通过专门的方法进行插入。
JDBCDemo05:
package com.redking.jdbc.demo;    
import java.io.BufferedReader;    
import java.io.IOException;    
import java.io.InputStreamReader;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.PreparedStatement;    
import java.sql.SQLException; 
public class JDBCDemo05 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                String name = null;    
                int age = 0;    
                BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));    
                System.out.println("请输入姓名:");    
                try {    
                        name = buf.readLine();    
                } catch (IOException e1) {    
                        e1.printStackTrace();    
                }    
                System.out.println("请输入年龄:");    
                try {    
                        age = Integer.parseInt(buf.readLine());    
                } catch (NumberFormatException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                } catch (IOException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                }    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                PreparedStatement pstmt = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                String sql = "INSERT INTO person(name,age) VALUES (?,?)";    
                System.out.println(sql);    
                try {    
                        //现在暂时占着,只是还不执行哈~    
                        pstmt = conn.prepareStatement(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                //执行语句之前必须设置内容    
                try {    
                        //设置好内容    
                        pstmt.setString(1,name);    
                        pstmt.setInt(2, age);    
                        //执行数据库更新操作    
                        pstmt.executeUpdate();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        pstmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    
}
看下效果,现在有没报错哈~
image
看下数据库中有没写入了哈~
image
一般在实际的开发中都去使用PreparedStatement,而很少会有人去直接使用Statement进行操作。 
进行查询: 
一般查询指的是执行SELECT 语句,SELECT 语句执行后实际上是会返回一组的数据(在内存中保存的)。 
必须使用ResultSet接口进行接收,实际此处也不是很清楚会有多行数据。
image
Next()表示把指针向下移动一个位置。
JDBCDemo06:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.PreparedStatement;    
import java.sql.ResultSet;    
import java.sql.SQLException;    
public class JDBCDemo06 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";    
        public static final String DBURL = "jdbc:odbc:testDB";    
        public static void main(String[] args) {    
                //数据库连接对象    
                Connection conn = null;    
                //数据库操作对象    
                PreparedStatement pstmt = null;    
                //数据库查询结果集对象    
                ResultSet rs = null;    
                //1、加载驱动程序    
                try {    
                        Class.forName(DBDRIVER);    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                //2、连接数据库    
                //通过连接管理器连接数据库    
                try {    
                        conn = DriverManager.getConnection(DBURL);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //3、向数据库中插入一条数据    
                //查询全部数据,查询数据的时候绝对不要写“*”    
                String sql = "SELECT id,name,age FROM person";    
                System.out.println(sql);    
                try {    
                        //现在暂时占着,只是还不执行哈~    
                        pstmt = conn.prepareStatement(sql);    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //4、执行语句    
                //执行语句之前必须设置内容    
                try {    
                        //执行数据库查询操作,返回的结果全部放在ResultSet之中    
                        rs = pstmt.executeQuery();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //下面开始依次循环取出内容,先判断后面有没内容,如果有则输出哈~    
                try {    
                        while(rs.next()){    
                                //Result必须按类型取值    
                                int id = rs.getInt("id");    
                                String name = rs.getString("name");    
                                int age = rs.getInt("age");    
                                System.out.println("ID = "+id+";name = "+name+";age = "+age);    
                        }    
                } catch (SQLException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                }    
                //5、关闭操作,步骤相反哈~    
                try {    
                        rs.close();    
                        pstmt.close();    
                        conn.close();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
        }    
}
看下效果:
image
总结JDBC操作数据库的整体步骤: 
1、加载驱动程序: 
|- Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ; 
2、连接数据库: 
|- Connection conn = DriverManager.getConnection("jdbc:odbc:testDB") ; 
3、实例化操作对象: 
|- Statement stmt = conn.createStatement() ;  --> 本身是没有SQL语句的 
|- PreparedStatement pstmt = conn.prepareStatement(sql) ;  -->  在实例化时必须有SQL语句 
4、进行数据库的CRUD操作 
|- Statement 
|- 更新:public int executeUpdate(sql) 
|- 查询:public ResultSet executeQuery(sql) 
|- PreparedStatement 
|- 更新:先进行设置值(setXxx()),public int executeUpdate() 
|- 查询:public ResultSet executeQuery() ; 
|- ResulSet: 
|- 所有的查询记录全部放在此对象之中,通过getXxx()方法取得 
|- 取得的时候可以直接写入列的名称 
|- 也可以写入编号 
5、关闭操作:先开后关的原则 
|- 如果有查询,则先关闭查询 
|- 关闭操作对象(PreparedStatement) 
|- 关闭数据库的连接
以上为JDBC 1.0中规定的标准操作。 
那么实际上现在的JDBC版本升高,最常用的只有一个批处理的操作。 
批处理就是要么全部成功,要么全部失败。
JDBCDemo07:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo07 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver" ;    
        public static final String DBURL = "jdbc:odbc:testDB" ;    
        public static void main(String[] args) {    
                Connection conn = null ;    
                Statement pstmt = null ;    
                try {    
                        // 向JAVA容器中加载驱动    
                        Class.forName(DBDRIVER) ;    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                try {    
                        conn = DriverManager.getConnection(DBURL) ;    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                try {    
                        pstmt = conn.createStatement() ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael001',31)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael002',32)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael003',33)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael'http://redking.blog.51cto.com',34)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael005',35)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael006',36)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael007',37)") ;    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //现在执行数据库的更新操作    
                try {    
                        pstmt.executeBatch() ;    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                try {    
                        pstmt.close() ;    
                } catch (SQLException e) {    
                        // TODO Auto-generated catch block    
                        e.printStackTrace();    
                }    
                try {    
                        conn.close() ;    
                } catch (SQLException e) {    
                        // TODO Auto-generated catch block    
                        e.printStackTrace();    
                }    
        }    
}
看下效果:
image
image
现在所有的代码确实都加入到批处理中了,但是却有点不妥当,因为在出错之前的语句都正确执行了,而出错之后的代码没有执行。应该是如果有一个出错了,则全部应该停止执行。
也就是说我们现在的程序缺少了一个事务的处理。 
事务处理之前必须进行取消自动提交,在默认情况下,所有的数据都是被默认提交上去的,就是说只要一执行更新就提交。 
取消自动提交之后,如果最后程序的代码(批处理代码)没有出错,则可以进行人为的手工提交。最后如果程序出现了错误,则应该进行回滚。
JDBCDemo07完善代码:
package com.redking.jdbc.demo;    
import java.sql.Connection;    
import java.sql.DriverManager;    
import java.sql.SQLException;    
import java.sql.Statement;    
public class JDBCDemo07 {    
        public static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver" ;    
        public static final String DBURL = "jdbc:odbc:testDB" ;    
        public static void main(String[] args) {    
                Connection conn = null ;    
                Statement pstmt = null ;    
                try {    
                        // 向JAVA容器中加载驱动    
                        Class.forName(DBDRIVER) ;    
                } catch (ClassNotFoundException e) {    
                        e.printStackTrace();    
                }    
                try {    
                        conn = DriverManager.getConnection(DBURL) ;    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                try {    
                        pstmt = conn.createStatement() ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael001',31)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael002',32)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael003',33)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael'http://redking.blog.51cto.com',34)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael005',35)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael006',36)") ;    
                        pstmt.addBatch("INSERT INTO person(name,age) VALUES ('Michael007',37)") ;    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                }    
                //取消自动提交    
                try {    
                        conn.setAutoCommit(false);    
                } catch (SQLException e1) {    
                        // TODO Auto-generated catch block    
                        e1.printStackTrace();    
                }    
                //现在执行数据库的更新操作    
                try {    
                        pstmt.executeBatch() ;    
                        //如果没有错误,则表示可以向下执行    
                        //手工提交    
                        conn.commit();    
                } catch (SQLException e) {    
                        e.printStackTrace();    
                        //如果出错了,则应该把数据回滚    
                        try {    
                                conn.rollback();    
                        } catch (SQLException e1) {    
                                // TODO Auto-generated catch block    
                                e1.printStackTrace();    
                        }    
                }    
                try {    
                        pstmt.close() ;    
                } catch (SQLException e) {    
                        // TODO Auto-generated catch block    
                        e.printStackTrace();    
                }    
                try {    
                        conn.close() ;    
                } catch (SQLException e) {    
                        // TODO Auto-generated catch block    
                        e.printStackTrace();    
                }    
        }    
}
看下效果:
image
程序报错后数据全部没有加进来哈~
image 
如果将第四条记录修改正确,那么七条数据就全写进数据库了哈~
image
JDBC-ODBC 的操作实际上在程序开发中是很不常用的,一般都会去直接使用JDBC 连接,但是由于Access的特殊性。
##############################################