本文共 7815 字,大约阅读时间需要 26 分钟。
JDBC (JavaDatabase Connectivity) 是用于执行SQL 语句的Java 应用程序接口,由一用Java 语言编写的类和接口组成。
JDBC 是一种规范,各数据库厂商为Java 程序员提供标准的数据库访问类和接口,使得独立于DBMS 的Java 应用程序的开发工具和产品成为可能。
JDBC TM是一种应用编程接口,它制定处理表格数据和常见的关系型数据的标准框架
数据库的基本概念:
数据库本质上是表的“智能”容器。
表是由行组成的容器。 行(概念上) 是由列组成的容器。列是具有名称、类型和值的单个数据项目。
SQL 非常适合于操作数据库,但其设计目的是仅作为与数据库通信的工具而设计的,还需要一个更通用和更完整的编程语言,来安排SQL 语句和向数据库输入,并处理结果以供数据操作、视觉显示或报表生成。
编写正确且遵守规范的Java 程序,可以无需重新编译就在任何启用Java技术的平台上运行。启用Java 技术的平台必须支持已知的核心库。
java.sql 包或JDBC 就是这样的一个库,它们可以视为ODBC的可移植版本,且其本身就是重大的标准。 Java 编程语言和JDBC 一起使用,可以给编写数据库应用程序提供正确的可移植性解决方案
JDBC 驱动程序属于类,它实现JDBC 驱动程序界面,并可以为特别的数据库转换程序(一般是SQL) 请求。
大多数的数据库供应商现在都提供驱动程序,以实现特定系统的JDBC API。这些通常都是免费提供的。第三方驱动程序也可以获得。
Sun Microsystems维护着包括来自众多厂商的超过200 个JDBC 驱动程序。
主要由以下界面(interface) 和类组成:
Driver (interface)
DriverManager (class):驱动管理类通过获取不同数据库的驱动类实现不同的登录方式。
Connection (interface): 用于和数据库进行连接类。
Statement (interface):用于执行静态sql语句
PreparedStatement (interface):用于执行预编译的sql语句,语句中使用?来传值,安全的查询方式。
CallableStatement (interface):用于调用存储过程函数。
ResultSet (interface):游标对象抓取行。
DatabaseMetaData (interface):可以获取数据库的结构信息,表信息,视图
ResultSetMetaData(interface):可以用于获取查询列的信息
1.首先,要将“驱动程序”传递到DriverManager
2.然后获得“连接”
3.其次,创建Statement、PreparedStatement、或CallableStatement,并将它们用于更新数据库或执行查询
4.最后,查询返回包含有已请求数据的ResultSet,ResultSet 是按“类型”检索的。 DatabaseMetaData 和ResultSetMetaData 接口可以用来提供有关数据库或ResultSet的信息。
连接数据库
public static Connection getConnection() throws Exception{ //连接数据库的四要素 //mysql URL 是 jdbc:mysql://ip地址:3306(端口)/数据库名 //oracle URL 是 jdbc:oracle:thin:@ip地址:1521:sid(orcl) String url = "jdbc:mysql://localhost:3306/test"; //告诉jdbc使用的是什么数据库 不同数据提供一些不同类型 String driverClass="com.mysql.jdbc.Driver"; // String username="root"; String password="123456"; //需要jvm加载该类 Class.forName(driverClass); //登录成功 Connection con = DriverManager.getConnection(url,username,password); return con; }查询
public static List结果
JDBC 主要有两种接口,分别是面向程序开发人员的JDBC API 和面向底层的JDBC Driver API,如下图所有:
JDBC API 是一系列抽象的接口,它使得应用程序员能够进行数据库连接,执行SQL 语句,并且得到返回结果
一些重要的接口和类:
java.sql.DriveManager:用来处理装载驱动程序并且为创建新的数据库连接提供支持。java.sql.Connection:完成对某一指定数据库连接功能。java.sql.Statement:在一个给定的连接中作为SQL执行声明的容器;它包含了两个重要的子类型。java.sql.PrepareStatement:用于执行预编译的SQL 声明。java.sql.CallableStatement:用于执行数据库中存储的过程的调用。java.sql.ResultSet:控制对于给定声明取得结果列的途径。
JDBC Driver API 是面向驱动程序开发商的编程接口,对于大多数数据库驱动程序来说,仅仅实现JDBC API 提供的抽象的类就可以了。
当java.sql.DriveManager 需要为一个特定的数据库URL 装载驱动程序时,每个驱动程序就需要提供一个能实现java.sql.Driver 接口的类。
JDBC 驱动程序根据其实现方式分为4 种类型:
JDBC-ODBC 桥是一个JDBC 驱动,它把JDBC调用转换为ODBC 操作。这个桥使得所有支持ODBC 的DBMS 都可以和Java 应用程序交互。
JDBC-ODBC 桥接口作为一套共享动态C 库提供的。ODBC 提供了客户方一套适合于客户方操作系统的库和驱动。这些ODBC 调用都是C 调用,而且客户必须带有ODBC 驱动和相关的客户方库的本地副本。这限制了它在基于Web 的应用程序中的使用。
本地Java 驱动程序( native-API partly-Java driver ),因为它们直接将JDBC API 翻译成具体数据库的API。将JDBC调用转换为对数据库的客户端API 的调用。
(net protocol all-Java driver (JDBC Proxy)),它将JDBC API 转换成独立于数据库的协议。JDBC 驱动程序并没有直接和数据库进行通讯;它和一个中间件服务器通讯,然后这个中间件服务器和数据库进行通讯。这种额外的中间层次提供了灵活性:可以用相同的代码访问不同的数据库,因为中间件服务器隐藏了Java 应用程序的细节。
(native protocol all-Java driver ),它直接与数据库进行通讯。 很多程序员认为这是最好的驱动程序,因为它通常提供了最佳的性能,并允许开发者利用特定数据库的功能。当然,这种紧密耦合会影响灵活性,特别是如果您需要改变应用程序中的底层数据库时。 这种驱动程序通常高度分布的应用程序。
使用JDBC 提供的API 对数据库进行操作。
1、建立数据库连接
2、创建数据库表
3、查询数据库
4、修改表数据
1. 加载Sun 公司的jdbc-odbc 驱动程序
Class.forName(“com.mysql.jdbc.Driver");
2. 加载Oracle 的驱动程序
Class.forName("oracle.jdbc.driver.OracleDriver");
3. 加载Microsoft SQL Server 的驱动程序
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
DriverManager 类的getConnection(String url) 方法用于建立与某个数据源的连接。
每个JDBC 驱动程序使用一个专门的JDBC URL 作为自我标识的一种方法。 JDBC URL 的格式为:jdbc:sub-protocol:database locator。子协议(sub-protocol) 与JDBC 驱动程序有关,可以是odbc、oracle、db2 等等,根据实际的JDBC 驱动程序厂商而不同。
数据库定位器(database locator) 是与驱动程序有关的指示器,用于唯一指定应用程序要和哪个数据库进行交互。根据驱动程序的类型,该定位器可能包括主机名、端口和数据库系统名。
String url = “jdbc:odbc:pubsdb”;Connection con = DriverManager.getConnection(url);//或者Connection con = DriverManager.getConnection(url, username,password);
//1. Sun的jdbc-odbc 驱动的URL url = “jdbc:odbc:pubsdb”;//2. Microsoft SQL Server 的URL url=“jdbc:microsoft:sqlserver://127.0.0.1:1433;databaseName=mydb”;//3. Oracle 的URL url=“jdbc:oracle:thin:@127.0.0.1:1521:myora”;//4.mysql 的URL url=“jdbc:mysql://127.0.0.1:3306/mydb;
1.atement 对象在每次执行SQL 语句时都将该语句传给数据库,在多次执行同一语句时,这样做效率较低。
2.可以使用PreparedStatement 对象。如果数据库支持预编译,它可以将SQL语句传给数据库作预编译,以后每次执行这个SQL 语句时,速度就可以提高很多。如果数据库不支持预编译,则在语句执行时,才将其传给数据库。这对用户来说是透明的。
3.eparedStatement 对象的SQL 语句还可以接收参数。在语句中指出需要接收哪些参数,然后进行预编译。在每一次执行时,可以给SQL 语句传输不同的参数,这样就大大提高了灵活性。
4.eparedStatement 接口是Statement 接口派生的子接口,因此它可以使用Statement接口中的方法。
如何把一系列语句组织成一个事务?
如果事务中所有命令都能正确执行,就可提交这个事务;否则,如果事务中有一个命令出现错误,回滚这个事务,并返回到提交以前的状态,好像什么也没有发生。
把所有命令组合成事务的主要目的是为了保证数据库的完整性。
对于一个事务而言,要么事务中语句全部得到正确执行,事务可被提交了,要么它中间出现错误。后一种情况,可以调用rollback() 方法,数据库将自动放弃上一次提交事务以来的全部变化。
一个数据库连接的缺省模式是autocommit 模式,每个SQL 命令一执行就会提交给数据库。一旦某个命令已提交,就不能把它退回。
可以用Connection 接口的getAutocommit() 方法,检验数据库的目前自动提交模式设置。
用命令con.setAutoCommit(false) 方法关闭自动提交模式。
用con.commit() 命令提交事务。
用con.rollback() 回滚一个事务。
很多数据库都支持在数据库内部执行的函数。这种方法有几个好处,包括更快的性能和改进的安全性。这些函数称为存储过程,而且虽然它们通常是用SQL 编写的,但也可以用数据库支持的任何编程语言编写。
随着Java 语言日趋流行,几个数据库厂商(包括Oracle 和IBM) 都启用了Java语言创建存储过程,还可以在不同数据库之间移动存储过程。存储过程可以支持三种类型的参数:IN、OUT 和INOUT,这对于存储过程在数据库内部真正能做什么来说,带来了很大的灵活性。
不管存储过程是用什么语言编写的,它都能以一种标准的方式从Java 应用程序调用。
首先,您需要创建一个CallableStatement 对象。为了标识存储过程和过程需要的参数的类型和数量,还要允许使用三种类型的调用。下面的清单说明了这三种类型(假定我们正在调用一个名为AuthorList 的存储过程):
1、 {call AuthorList} 如果过程不需要参数
2、 {call AuthorList[(?, ?)]} 如果过程需要两个参数3、 {? = call AuthorList[(?, ?)]} 如果参数需要两个参数并返回一个
PreparedStatement ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); for(int i=0; i<1000; i++) { ps.setString(1,"Batch Name"+i); ps.setDate(2, new java.sql.Date(System.currentTimeMillis())); ps.setFloat(3, 3333.33f); ps.addBatch();//将数据打包 } ps.executeBatch();//执行打包后的sql
JDBC的元数据接口有:
DatabaseMetaData数据库级
ResultSetMetaData结果集级
在对数据源进行连接以后,得到一个Connection 的对象,可以从这个对象获得有关数据源的各种信息,包括关于数据库中的各个表,表中的各个列,数据类型和存储过程等各方面的信息。 根据这些信息,JDBC 程序可以访问一个事先并不了解的数据库。获取这些信息的方法都是在DatabaseMetaData 的对象上实现的,而DatabaseMetaData 对象是在Connection 对象之上获得的。
以在一个连接的基础上创建一个DatabaseMetaData 对象;
DatabaseMetaDatadbma =con.getMetaData();
例:
//批处理 批量导入数据public static void processingBatch(List> list) throws Exception{ //获取与数据库的连接 Connection con = getConnection(); String sql = "insert into stu values(?,?,?,?)"; //用于执行预编译的sql语句,语句中使用?来传值,安全的查询方式。 PreparedStatement pst = con.prepareStatement(sql); for(Map map:list){ pst.setInt(1,Integer.valueOf(map.get("s"))); pst.setString(2, map.get("sname")); pst.setInt(3,Integer.valueOf(map.get("sage"))); pst.setString(4, map.get("ssex")); //加入批处理 pst.addBatch(); } pst.executeBatch(); pst.close(); con.close();}