JDBC-ODBC桥接器
创建了一个数据源,这个数据源就是一个数据库。为了连接到这个数据库,需要建立一个JDBC-ODBC桥接器,即加载桥接器驱动程序。
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
这里Class是包java.lang中的一个类,该类通过调用它的静态方法forName就可以建立JDBC-ODBC桥接器。建立桥接器时可能发生异常,所以建立桥接器代码要放到try-catch语句块中。
查询记录
步骤1:连接到数据库
首先使用包java.sql中的Connection类声明一个对象,然后再使用类DriverMamager调用它的静态方法getConnection创建这个连接对象:
Connection con = DriverMamager.getConnection("jdbc:odbc:数据源名字","用户名","密码");
假如没有为数据源设置用户名和密码,那么连接方式是:
Connection con = DriverMamager.getConnection("jdbc:odbc:数据源名字","","");
例如:
try{
Connection con = DriverMamager.getConnection("jdbc:odbc:myDB","sa","sa");
}catch(SQLException e){}
步骤2:向数据库发送SQL语句
首先使用Statement类声明一个SQL语句对象,然后通过刚才创建的连接数据库的对象con调用方法createStatement()创建这个SQL语句对象:
try{
Statement sql = con.createStatement();
}catch(SQLException e){}
有了SQL语句对象后,这个对象就可以调用相应的方法实现对数据库中表的查询和修改,并将查询结果存放在一个ResultSet类声明的对象中。也就是说,SQL语句对数据库的查询操作将返回一个ResultSet对象:
ResultSet rs = sql.executeQuery("SQL语句");
ResultSet对象是由统一形式的列组织的数据行组成。ResultSet对象一次只能看到一个数据行,使用next()方法走到下一数据行。获得一行数据后,ResultSet对象可以使用getXXXX方法获得字段值,将位置索引(第一列使用1,第二列使用2等)或字段名传递给getXXXX方法的参数即可。
ResultSet类的若干方法
返回类型 | 方法名 |
Boolean | next() |
Byte | getByte(int columnIndex) |
Date | getDate(int columnIndex) |
Double | getDouble(int columnIndex) |
Float | getFloat(int columnIndex) |
Int | getInt(int columnIndex) |
Long | getLong(int columnIndex) |
String | getString(int columnIndex) |
Byte | getByte(String columnName) |
Date | getDate(String columnName) |
Double | getDouble(String columnName) |
Float | getFloat(String columnName) |
Int | getInt(String columnName) |
Long | getLong(String columnName) |
String | getString(String columnName) |
顺序查询
使用结果集Result的next()方法,可以顺序地查询。一个结果集最初将游标定位在第一行的前面,第一次调用next()方法使游标移动到第一行。next()方法返回一个boolean型数据。当游标移动到最后一行之后返回false。
流动查询
有时候我们需要在结果集中前后移动或显示结果集指定的一条记录等等。这时,我们必须要返回一个可滚动的结果集。为了得到一个可滚动的结果集,我们必须使用以下方法获得一个Statement对象:
Statement stmt = con.createStatement(int type,int concurrency);
然后,根据参数type、concurrency的取值情况,stmt返回相应类型的结果集。
type的取值决定滚动方式,取值可以是:
■ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。
■ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动。当数据库变化时,当前结果集不变。
■ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集。当数据库变化时,当前结果集同步改变。
concurrency的取值决定是否可以用结果集更新数据库。concurrency取值可以是:
■ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。
■ResultSet.CONCUR_UPDATABLE 能用结果集更新数据库中的表。
滚动查询经常用到的ResultSet的方法有:
方法 | 作用 |
public boolean previous() | 将游标向上移动,该方法返回boolean型数据,当移动到结果集第一行之前时返回false。 |
public void beforeFirst() | 将游标移动到结果集的初始位置,即在第一行之前。 |
public void afterLast() | 将游标移到结果集最后一行之后。 |
public void first() | 将游标移到结果集的第一行。 |
public void last() | 将游标移到结果集的最后一行。 |
public boolean isAfterLast() | 判断游标是否在最后一行之后。 |
public boolean isBeforeFirst() | 判断游标是否在第一行之前。 |
public boolean ifFirst() | 判断游标是否指向结果集的第一行。 |
public boolean isLast() | 判断游标是否指向结果集的最后一行。 |
public int getRow() | 得到当前游标所指行的行号。行号从1开始,如果结果集没有行,返回0。 |
public boolean absolute(int row) | 将游标移到参数row指定的行号。 |
随机查询
用Math类的静态方法random()可以产生一个大于0小于1的随机数。用公式:
int i = (int)(Math.random()*number+1);
可以产生一个1到number之间的随机数。根据这个随机数将游标移动到相应的行,并输出行。
参数查询
可以由文本框获取参数,作为SQL语句的条件进行查询。如:从text框获取值作为“姓名”进行查询:
String name1 = request.getParameter("text");
······
String condition = "select * from student where name = "+" ' "+name1+" ' ";
······
排序查询
可以在SQL语句中使用ORDER BY子语句对记录排序。如:使用SQL语句的ORDER BY子语句查询所有同学的成绩,可以选择按3科的总分从低到高排列记录、按姓氏的拼音排序或按英语成绩排序。
分析结果集查询
通过分析结果集来输出记录。如:查询所有姓罗的同学的成绩,首先判断结果集中姓氏字段的值是否某个姓氏,然后输出全部该姓氏的同学的成绩。
使用通配符查询
可以用SQL语句操作符LIKE进行模式般配,使用“%”代替一个或多个字符,用一个下划线“_”代替一个字符。比如:下述语句查询姓名是罗的记录:
rs = sql.executeQuery("select * from student where name like '罗%' ");
更新记录
Statement对象调用方法:public int executeUpdate(String sqlStatement);
通过参数sqlStatement指定的方式实现对数据库表中记录的字段值的更新。如:将表student中张三的数学成绩字段值更新为80:
executeUpdate("update student set math = 80 where name='张三' ");
虽然可以使用Statement对象进行更新和查询操作,但需要注意的是,当查询语句返回结果集后,如果没有立即输出结果集的记录,而接着执行更新语句,那以结果集就不能输出记录了。要想输出记录就必须重新返回结果集。
添加记录
Statement对象调用方法:
public int executeUpdate(String sqlStatement);
通过参数sqlStatement指定的方式实现向数据库表中添加新的记录。如:向表student中添加一条新的记录
('199911','李四',100,90,80):
executeUpdate("insert into student values('199911','李四',100,90,80)");
跟更新记录一样,当查询语句返回结果集后,如果没有立即输出结果集的记录,而接着执行添加语句,那以结果集就不能输出记录了。要想输出记录就必须重新返回结果集。
删除记录
Statement对象调用方法:
public int executeUpdate(String sqlStatement);
通过参数sqlStatement指定的方式实现向数据库表中添加新的记录。如:要删除学号是1234的记录:
executeUpdate("delete from student where id = '1234' ");
跟更新记录以及添加记录一样,当查询语句返回结果集后,如果没有立即输出结果集的记录,而接着执行删除语句,那以结果集就不能输出记录了。要想输出记录就必须重新返回结果集。
用结果集更新数据库中的表
尽管可以用SQL语句对数据库中的表进行更新,但也可以使用内存中的ResultSet对象对底层数据库进行更新,步骤如下:
步骤1:由Connection对象调用如下方法,到一个可以更新底层数据库的Statement对象sql:
createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
步骤2:Statement对象sql调用如下方法得到ResultSet对象rs:
executeQuery("select * from 表名");
步骤3:rs调用相应updateXXX的方法对rs中所有的行的列值进行更新操作。如:
rs.updateInt(3,10088);
步骤4:将rs移动到第n行后,调用pudateRow()方法,更新底层数据库表中的第n条记录。rs也可以调用rs.insertRow()方法将更新的结果集作为一条新的记录插入到底层数据库表中。如果rs的某列的值未被更新,那么插入到底层数据库表中的记录的相应字段值为null。
ResultSet对象的一些常用的更新操作方法:
■updateInt(String columnName,int x) , pudateInt(int columnIndex,int x)
■updateLong(String columnName,long x) , pudateLong(int columnIndex,long x)
■updateDouble(String columnName,double x) , pudateDouble(int columnIndex,double x)
■updateString(String columnName,String x) , pudateString(int columnIndex,String x)
■updateBoolean(String columnName,boolean x) , pudateBoolean(int columnIndex,boolean x)
■updateDate(String columnName,Date x) , pudateDate(int columnIndex,Date x)
分页显示记录
简单地实现数据库表中记录的分页显示,假设总记录数为m,每页显示数量为n,那么总页数的计算公式是:
■如果m除以n的余数大于0,总页数等于m除以n的商加1。
■如果m除以n的余数大于0,总页数等于m除以n的商。
即
总页数 = (m%n==0)?(m/n):(m/n+1);
如果准备显示第p页的内容,应当把游标移动到第(n-1) *n+1条记录处。
查询Excel电子表格
有时需要查询Excel电子表格工更新删除Excel电子表格的内容,可以通过JDBC-ODBC桥接器访问Excel电子表格。步骤如下:
步骤1:设置数据源
为数据源选择的驱动程序是Microsoft Excel Driver
步骤2:选择表
与访问其他数据库不同的是,必须在电子表格中选出一工作区作为连接时使用的表。在Excel电子表格中搬运鼠标迁出范围,然后在Excel菜单中选择“插入”—“名称”—“定义”,给选中的工作区命名(这一工作区的名称将作为连接时使用的表名)。
使用同步连接
数据库操作中,建立连接是耗时最大的操作之一。如果客户访问的是同一数据库,那么,为每个客户都建立一个连接是不合理的。在“<%!”与“%>”之间声明的变量在整个JSP页面内都有效,因为JSP引擎将JSP页面转译成JAVA文件时,将这些变量作为类的成员变量。这些变量的内存空间直到服务器关闭才释放。当多个客户请求一个JSP页面时,JSP引擎为每个客户启动一个线程而不是启动一个进程,这些线程由WEB服务器进程来管理,它们共享JSP页面的成员变量。在处理多线程问题时,可以将线程共享的变量放入一个synchronized块,或将修改该变量的方法用synchronized来修饰,这样,当一个客户用synchronized块或synchronized方法修改一个共享变量时,其他线程就必须等待,直到该线程执行完该方法或同步块。这样,我们可以把Connection对象作为一个成员变量被所有客户共享,也就是说,第一个访问数据库的客户负责建立连接,以后所有客户共享这个连接。
例:网上投票
我们创建一个Access数据库vote.mdb,将该数据库设置为一个数据源,数据源的名字是vote。该库含有2个表“people”和“IP”。people表存放候选人的名字和得票数。IP表存放投票人的IP地址。投票之前,我们要把候选人的名字和初始得票数存入people表中。
投票系统由两个页面组成:vote.jsp和startvote.jsp。vote.jsp页面按着people表中的候选人生成一个投票的表单。startvote.jsp页面获取vote.jsp页面提交的候选人的名字。该页面在进行投票之前,首先查询IP表,判断该用户的IP地址是否已经投过票。如果该IP地址没有投过票,就可以参加投票,投票以后,将投票用户的IP地址写入数据库的IP表中。对于动态分配IP地址的用户无效。