简单的学习JDBC
来源:互联网 发布:倒计时软件哪个好 编辑:程序博客网 时间:2024/05/21 17:00
为什么学习JDBC ?
数据库编程是企业编程重要一部分,不可能不接触。在没有JDBC之前,使用的是ODBC,其实就是调用数据库厂家自己的API来做编程,可移植性差。自从有了JDBC,数据库的编程有了相对统一的编程模式。在这个基础上又有了hibernate这样的JAVA的数据持久化层,更加增加了程序可移植性。
其实C++也有类似的框架,例如Sqlite。C++自己的问题就是可移植性差,导致现在使用C++做企业编程的人很少,Sqlite也基本没人用。至少我在C++上面使用postgresql时候都是直接调用postgresql的API。当然也可能TSC是小程序而且也没打算跨平台,那么效率和编程量就优先一些。
哪些JAVA程序使用JDBC?JDBC原理是什么?
JDBC可以被使用在任何JAVA程序中,包括EJB、servlet、applet。在没有hibernate之前,都是手动编写JDBC程序调用SQL语句,然后使用结果集进行处理。
一次书写,到处debug是JAVA的目标,也是JDBC的目标。JDBC封装了数据库的API,sql包中主要继承了JAVA的三部分(看书):exception、data、object。中间层使用JDBC驱动,底层还是数据库自己的协议。有些公司招聘就是招聘JDBC-ODBC驱动,主要招聘C,这个话题略过。
基本的JDBC如何使用?
使用JDBC必须包括java.sql.*包。使用的基本流程见下。另外从这里也稍微看出来JAVA与C++的code style区别。1是{}在前导句下面;2是C++使用iterator时候使用++,而JAVA这里使用next;3是API的命名规范,第一个单词小写,后面的头一个字母大写,这也是规范的写法。可能平时我写的不规范吧。类名第一个字母就要大写。4是JAVA的class之后不需要分号,而C++的class由于与struct有关联,所以还是有分号。5是JAVA中栈上不分配对象,只有指针,所有对象都存在于堆,也就是程序中想要使用对象只有一种方法,那就是new出来。
这个流程只是最简单的JDBC流程,另外还有认证的使用,SQL的修改等。下面也能看到JAVA面向对象的编程方法,所有的数据与操作都采用对象实现。例如con、sm、rs。如果使用C的话,就是连接、查询、使用、回写这种面向过程的想法。而在JAVA中,就是建立连接对象、使用连接对象建立上下文、使用上下文进行查询、使用查询结果、使用上下文回写结果集。
import java.sql.*
...
public class jdbcexp {
public static void main(String args[]) {
...
// 加载数据库包
try
{
Class.forName("驱动公司的java包"); //import公司驱动包进来
}
catch(Exception e)
{
...
}
// 连接数据库
try
{
con = DriverManager.getConnection(url); // step 1
sm = con.createStatement(); // step 2
rs = sm.excuteQuarry("Sql语句"); // step 3
while (rs.next())
{
process(rs); // step 4
}
}
catch (SQLException e)
{
}
finally
{
try
{
rs.close();
sm.close();
con.close(); // step 5, 注意顺序。
}
catch (SQLException e)
{}
}
}
}
高级JDBC使用?
将SQL语言分布在java程序中,如上所写,不是好主意。这样有几个问题,一是移植性差,例如给oracal写的程序移植到sybase上面时候要修改SQL语句。二是控制分散在程序中,要修改逻辑会很复杂,例如现在要为querry语句加个filter,还需要在java程序中修改。
数据库编程是企业编程重要一部分,不可能不接触。在没有JDBC之前,使用的是ODBC,其实就是调用数据库厂家自己的API来做编程,可移植性差。自从有了JDBC,数据库的编程有了相对统一的编程模式。在这个基础上又有了hibernate这样的JAVA的数据持久化层,更加增加了程序可移植性。
其实C++也有类似的框架,例如Sqlite。C++自己的问题就是可移植性差,导致现在使用C++做企业编程的人很少,Sqlite也基本没人用。至少我在C++上面使用postgresql时候都是直接调用postgresql的API。当然也可能TSC是小程序而且也没打算跨平台,那么效率和编程量就优先一些。
一次书写,到处debug是JAVA的目标,也是JDBC的目标。JDBC封装了数据库的API,sql包中主要继承了JAVA的三部分(看书):exception、data、object。中间层使用JDBC驱动,底层还是数据库自己的协议。有些公司招聘就是招聘JDBC-ODBC驱动,主要招聘C,这个话题略过。
这个流程只是最简单的JDBC流程,另外还有认证的使用,SQL的修改等。下面也能看到JAVA面向对象的编程方法,所有的数据与操作都采用对象实现。例如con、sm、rs。如果使用C的话,就是连接、查询、使用、回写这种面向过程的想法。而在JAVA中,就是建立连接对象、使用连接对象建立上下文、使用上下文进行查询、使用查询结果、使用上下文回写结果集。
import java.sql.*
...
public class jdbcexp {
public static void main(String args[]) {
...
// 加载数据库包
try
{
Class.forName("驱动公司的java包"); //import公司驱动包进来
}
catch(Exception e)
{
...
}
// 连接数据库
try
{
con = DriverManager.getConnection(url); // step 1
sm = con.createStatement(); // step 2
rs = sm.excuteQuarry("Sql语句"); // step 3
while (rs.next())
{
process(rs); // step 4
}
}
catch (SQLException e)
{
}
finally
{
try
{
rs.close();
sm.close();
con.close(); // step 5, 注意顺序。
}
catch (SQLException e)
{}
}
}
}
采用分层与面向对象的思想,JDBC支持存储过程的使用。这样JDBC使用者只需要给出输入输出,同时也只关心输入输出。如果SQL工程师想要修改存储过程的逻辑,只需要修改相应的文件即可,也不需要告诉JAVA工程师。
数据库提供两种方式的优化,一是prepared SQL,一是存储过程。PreparedStatement是Statement的子类,实现了prepared SQL,基本想法是将多个查询合并成一个查询计划。但是prepared SQL不能实现代码的分离。CallableStatement实现了存储过程,这个子类可以通过注册param与使用JDBC的存储过程的语法实现。
class jdbcexp
{
...
public void insert (Transaction tran, Student student)
{
try
{
DatabaseTransaction dbtran = (DatabaseTransaction)tran;
Connection conn = dbtran.getConnection();
CallableStatement stm = con.preparedCall("BEGIN
sp_insert students(?,?,?);
END;");
stm.setInt(1, student.getId());
...
stm.excute(); // excute stm
stm.close(); // close stm
con.commit(); // commit con
con.close(); // close con
}
catch (SQLException e)
{
e.printStackTrack();
}
}
}
另一个JDBC支持的高级特性是动态存取,也就是数据持久化层的程序员并不知道上层应用会传递什么下来,也不知道应用会执行什么样的操作,JDBC采用了两种meta data实现。
java.sql.ResultSetMetaData extand了ResultSet,通过提供结果集属性的一些信息,使得程序员能根据不同的结果采取不同的方法。java.sql.DatabaseMetaData也是extend了Connection,通过提供属性信息方式,来实现动态特性。最后如下实现了一个动态存储的示例。
import java.sql.*
/**
* 使用JDBC实现数据库基本操作:
* commit、go(将缓冲区内容送往数据库)、quit、reset、rollback、show version
* 读程序的话从main开始向上读。
*/
class SqlAppExp {
private bool connected;
private Connection con; // 其实不用初始化
@method
private void processRes(Result res)
throw SQLException
{
// 这个方法是从元数据中操作SQL,基本是使用meta的API实现
try
{
ResultSetMetaData meta = res.getMetaData();
// 最终表格显示成如下形式:
// 第一列 | 第二列
// 值 | 值
...
int cols = meta.getColumnCount();
for (i=1; i<cols; i++)
{
process meta.getColumnXXX();
}
}
catch
{
}
}
@method
private void executeStm(String sql, Connection con)
throw SQLException
{
Statement stm = null;
try
{
stm = createStatement();
if (stm.execute(sql))
{
// 如果有结果集
ProcessRes(stm.getResultSet());
}
else
{
// 如果没有结果集
num = stm.getUpdateCount();
...
}
}
catch (SQLException e)
{
throw e;
}
finally
{
if (stm != null) // JAVA中最好不要使用C++的if(stm)这样的语句
{
try
{
stm.close();
}
catch(SQLException e)
{
process e ;
}
}
}
}
public static void main(String args[])
{
// some io before
// connect to database
try
{
Class.forName(driver); // RTTI机制
con = DriverManage.getConnection(url, props);
}
catch (SQLException e)
{
System.out.println("Can't connect to database");
return ;
}
catch (ClassNotFoundException e)
{
System.out.println("Missing database driver.");
return ;
}
// connect OK
System.out.println("Connection OK.");
connected = true;
reader = new java.io.InputStreamReader(System in); // 与下面一起,是装饰者模式的应用
input = new java.io.BufferReader(reader); // 首先将system in装饰为io stream,然后装饰为buffer
while (connected)
{
// omit io process
if (cmd.equals("commit"))
{
try
{
con.commit();
}
catch (SQLException e)
{
System.out.println("failed in commit");
}
}
else if (cmd.equals("go"))
{
if (!buffer.equals(""))
{
try
{
executeStm(buffer, connection);
}
catch (SQLException e)
{
System.out.println(e.getMessage());
}
}
}
else if (cmd.equals("quit"))
{
connected = false;
continue ;
}
else if (cmd.equals("reset"))
{
buffer = ""; // 如果是C++程序,还要释放buffer先(SAFE_FREE(buffer)),然后再给buffer开辟新空间,C++程序员真辛苦
...
continue ;
}
else if (cmd.equals("rollback"))
{
try
{
con.rollback();
}
...
}
else if (cmd.startsWith("show"))
{
some check here;
DatabaseMetaData meta;
try
{
meta = con.getMetaData();
process cmd here;
if (cmd.equals("version"))
{
showVersion(meta); // 这是自定义的函数
}
}
catch (SQLException e)
{
System.out.println("载入元数据失败," + e.getMessage()); // 这个提示比较重要
}
}
else // 如果输入的不是命令,那么就是SQL语句,将其加入缓冲区buffer就好,这就是元数据
{
buffer += input;
...
continue;
}
// close connection
try
{
con.close();
}
catch (SQLException e)
{
System.out.println("");
}
] }
}
}
/**
* 使用JDBC实现数据库基本操作:
* commit、go(将缓冲区内容送往数据库)、quit、reset、rollback、show version
* 读程序的话从main开始向上读。
*/
class SqlAppExp {
private bool connected;
private Connection con; // 其实不用初始化
@method
private void processRes(Result res)
throw SQLException
{
// 这个方法是从元数据中操作SQL,基本是使用meta的API实现
try
{
ResultSetMetaData meta = res.getMetaData();
// 最终表格显示成如下形式:
// 第一列 | 第二列
// 值 | 值
...
int cols = meta.getColumnCount();
for (i=1; i<cols; i++)
{
process meta.getColumnXXX();
}
}
catch
{
}
}
@method
private void executeStm(String sql, Connection con)
throw SQLException
{
Statement stm = null;
try
{
stm = createStatement();
if (stm.execute(sql))
{
// 如果有结果集
ProcessRes(stm.getResultSet());
}
else
{
// 如果没有结果集
num = stm.getUpdateCount();
...
}
}
catch (SQLException e)
{
throw e;
}
finally
{
if (stm != null) // JAVA中最好不要使用C++的if(stm)这样的语句
{
try
{
stm.close();
}
catch(SQLException e)
{
process e ;
}
}
}
}
public static void main(String args[])
{
// some io before
// connect to database
try
{
Class.forName(driver); // RTTI机制
con = DriverManage.getConnection(url, props);
}
catch (SQLException e)
{
System.out.println("Can't connect to database");
return ;
}
catch (ClassNotFoundException e)
{
System.out.println("Missing database driver.");
return ;
}
// connect OK
System.out.println("Connection OK.");
connected = true;
reader = new java.io.InputStreamReader(System in); // 与下面一起,是装饰者模式的应用
input = new java.io.BufferReader(reader); // 首先将system in装饰为io stream,然后装饰为buffer
while (connected)
{
// omit io process
if (cmd.equals("commit"))
{
try
{
con.commit();
}
catch (SQLException e)
{
System.out.println("failed in commit");
}
}
else if (cmd.equals("go"))
{
if (!buffer.equals(""))
{
try
{
executeStm(buffer, connection);
}
catch (SQLException e)
{
System.out.println(e.getMessage());
}
}
}
else if (cmd.equals("quit"))
{
connected = false;
continue ;
}
else if (cmd.equals("reset"))
{
buffer = ""; // 如果是C++程序,还要释放buffer先(SAFE_FREE(buffer)),然后再给buffer开辟新空间,C++程序员真辛苦
...
continue ;
}
else if (cmd.equals("rollback"))
{
try
{
con.rollback();
}
...
}
else if (cmd.startsWith("show"))
{
some check here;
DatabaseMetaData meta;
try
{
meta = con.getMetaData();
process cmd here;
if (cmd.equals("version"))
{
showVersion(meta); // 这是自定义的函数
}
}
catch (SQLException e)
{
System.out.println("载入元数据失败," + e.getMessage()); // 这个提示比较重要
}
}
else // 如果输入的不是命令,那么就是SQL语句,将其加入缓冲区buffer就好,这就是元数据
{
buffer += input;
...
continue;
}
// close connection
try
{
con.close();
}
catch (SQLException e)
{
System.out.println("");
}
] }
}
}
后续还要做什么?
学习JDBC只是开始,了解JDBC之后才能更好的学习JAVA的数据持化技术,例如JEE、hibernate。JDBC只是提供面向大多数数据库的适配层,更高级的持久化技术还包括buffer技术、数据库优化、面向对象数据库的应用、分布式数据库的应用等。
0 0
- 简单的学习JDBC
- 简单学习 JDBC的DAO模式
- JDBC简单学习
- 学习jdbc简单的数据库连接分享(sql2000)
- Java学习之---简单的JDBC连接Oracle
- JDBC学习笔记——简单的连接池
- 实例:简单的JDBC复习+MySql入门学习
- JDBC学习笔记一(简介与简单的实例)
- jdbc链接数据库进行简单的操作学习笔记
- JDBC的简单事务处理
- jdbc的简单案例
- JDBC的简单实现
- JDBC的简单实例
- 最简单的jdbc
- JDBC的简单介绍
- jdbc简单的连接
- Jdbc 简单的Alipay
- JDBC的简单介绍
- zip 数据压缩
- SAP Basis日常工作
- ORA-27300,ORA-27301,ORA-27302,ORA-27303导致实例宕的问题分析
- 用ShellExecuteEx和TerminateProcess打开和关闭文件
- 3Sum Closest
- 简单的学习JDBC
- Android应用常规开发技巧——善用组件生命周期
- Nginx配置总结2
- cocos2dx 如何制作一个使用世界坐标系的精灵
- LeetCode_64---Minimum Path Sum
- win7 下安装 Ubuntu系统
- POJ2406KMP
- Newtonsoft.Json高级用法
- [51单片机系列]1.外部中断