正在做一个升级项目project,project的意思就是不是application也不是platform,仅仅是一个project而已。
项目的需求之一就是对于升级前的数据,保存在access的*.mdb中的数据,继续能够访问。
我希望通过maven构建一个spring框架下的项目,那么目前的一个问题就是我的代码需要可以访问access数据库。
之前博文中,叙述了jdk8环境下java代码使用ucanaccess访问access数据库的过程。
接下来,也就是这篇博文,我希望讨论一下,在spring环境下,透过dbcp这个数据库连接池技术,使用ucannaccess访问access数据库的实现过程。
spring使用dbcp这个项目构建jdbc的连接池
ucanaccess这个项目,是Java JDBC的一个实现
“UCanAccess is a pure Java JDBC Driver implementation which allows java developers and jdbc client programs to read/write Microsoft Access database (.mdb and .accdb files). No ODBC needed.”
我希望使用spring,并导入dbcp的连接池,来操纵UCanAccess封装的方法去访问ms access数据库。
为什么要使用UCanAccess,而不是用Java语言自己的方法去访问ms access数据库呢?因为JDK8以后,Java语言自身不再提供jdbc-odbc bridge这类方法,也就是JDK8以后这部分方法被Java语言自己放弃了。UCanAccess的角色相当于“临时工”或者“外围”或者“龙套”。
dbcp依赖于JDK中的JDBC
"DBCP 2 compiles and runs under Java 7 only (JDBC 4.1)"
ucanaccess是JDBC的一个实现类
因此我推测,dbcp无法使用ucanaccess。
ucanaccess的作用是让java代码可以使用JAVA语言自身的DriverManager.getConnection("url","uname","pwd")方法
经过上述方法之后,就直接获取了Connection类的实例,也就是这以后的工作全都和ucanaccess无关了,全是java的工作了。
至此,我甚至怀疑抛开dbcp不谈,spring本身的JDBCTemplate是否能够使用ucanaccess都是个问题
经过代码验证,我的上述怀疑是错的。
最终的结论是,spring可以通过JdbcTemplate调用ucanaccess注册的链接,对ms access进行数据库访问。
下图为我这部分测试代码
看,顺利的使用Spring从access文件(*.mdb)中读取了数据。
下面我们来描述一下改造的过程。
首先,第一张图的理解有误应该修改成如下所示:
ucanaccess实现了java JDBC的部分功能,自愿成为“外围”也就是“临时工”,只要你的项目正确导入了它,那么日后的所有操作,你就当它不存在就可以了,或者说你就当ucanaccess是java的一部分就可以了。
Spring的子包 spring-jdbc 包含了我们这次改造用到的3个类:
1.DriverManagerDataSource类
2.JdbcTemplate类
3.RowCallbackHandler类
只要你的项目导入了Spring的spring-jdbc,那么你的代码就可以大大方方的使用DriverManagerDataSource创建一个ucanaccess注册的数据源,并把这个数据源提供给JdbcTemplate的实例,然后由这个实例执行JdbcTemplate的方法query()进行查询,这个方法具有回调方法,在回调方法中读取结果集中的数据,并System.out.println()显示出来。
首先,为我们的项目导入spring-jdbc
这里啰嗦一句,你是怎么知道你需要导入spring-jdbc的呢?
其实我也是百度的,而且spring的官网也没有写你应该在自己的项目导入哪些包。主要是我看书需要使用spring的DriverManagerDataSource类来注册数据源,我搜索了一下,这个类属于spring-jdbc
下面直接上代码:
package com.infotech.access;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import net.ucanaccess.jdbc.UcanaccessDriver;
/**
* @author Administrator
*
*/
public class AccessTest {
public static Connection conn2 = null;
public static Statement stmt2 = null;
public static ResultSet srs2 = null;
public static ResultSetMetaData rsmd2=null;
public Connection ucaConn = null;
public Statement stmt = null;
public ResultSet srs = null;
public ResultSetMetaData rsmd=null;
/**
* example 中提供的构造函数
*
*/
public AccessTest(String pathNewDB) {
try {
this.ucaConn=getUcanaccessConnection(pathNewDB);
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 自己写的构造函数
*/
public AccessTest(){
}
private static Connection getUcanaccessConnection(String pathNewDB) throws SQLException,IOException {
String url = UcanaccessDriver.URL_PREFIX + pathNewDB+";newDatabaseVersion=V2003";
return DriverManager.getConnection(url, "admin", "");
}
/**
* 连接access数据库的方法(测试可用)
*/
public void OpenConnAC()throws Exception{
try{
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
ucaConn=DriverManager.getConnection(UcanaccessDriver.URL_PREFIX + "\\\\172.16.30.106\\share\\入库检验_be.mdb" + ";newDatabaseVersion=V2003", "admin", "" );
ucaConn.setAutoCommit(false);
}
catch(Exception e){
System.err.println("OpenConnAC:exception"+e.getMessage());
}
}
/**
* 带有输入参数的executeQuery()
* @return
*/
public ResultSet executeQuery(String sql) {
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
srs = stmt.executeQuery(sql);
} catch (SQLException e) {
System.err.println("executeQuery:" + e.getMessage());
}
return srs;
}
/**
* 执行更新
*/
public void executeUpdate(String sql) {
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
stmt.executeUpdate(sql);
ucaConn.commit();
} catch (SQLException e) {
System.err.println("executeUpdate:" + e.getMessage());
}
}
/**
* 关闭资源
*/
public void close() {
try {
if (srs != null) {
srs.close();
}
if (stmt != null) {
stmt.close();
}
if (ucaConn != null) {
ucaConn.close();
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
/**
* used to return the num of the resultset
* @param 输入参数 sql语句
* @return 返回值 语句执行结果集的元素数目
*/
public int iRSNum(String sql) {
String sRsnum = "";
int iRsnum = 0;
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
srs = stmt.executeQuery(sql);
//System.out.println("----iRSNum()----");
} catch (SQLException e) {
System.err.println("executeQuery:" + e.getMessage());
}
try {
srs.last();
sRsnum = srs.getString(1);
iRsnum = Integer.parseInt(sRsnum);
} catch (SQLException e) {
e.printStackTrace();
}
return iRsnum;
}
/**
* @param sTname 输入参数 表 名
* @return 返回值 表 中记录数目
*/
public int iRSNum2(String sTname){
String sRsnum = "";
int iRsnum = 0;
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
System.out.println("Query OK");
srs = stmt.executeQuery("select count(*) from " + sTname);
} catch (SQLException e) {
System.err.println("executeQuery:" + e.getMessage());
}
try {
srs.last();
sRsnum = srs.getString(1);
iRsnum = Integer.parseInt(sRsnum);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("-------iRSNum2()--------");
return iRsnum;
}
/**
* @param 输入参数 select语句
* @return 返回值 Vector容器
*/
public Vector<Vector<String>> testF(String sql) {
int numCols = 0;
//int rowCount = 0;
String st = null;
Vector<Vector<String>> vo = new Vector<Vector<String>>();
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
srs = stmt.executeQuery(sql);
rsmd = srs.getMetaData();
numCols = rsmd.getColumnCount(); // 属性数目
srs.last(); // 移到最后一行
//rowCount = srs.getRow(); // 得到当前行号,也就是记录数
srs.beforeFirst();
while (srs.next()) {
Vector<String> v = new Vector<String>();
for (int j = 0; j < numCols; j++) {
st = srs.getString(j + 1) == null ? "" : srs.getString(j + 1);
v.addElement(st);
v.trimToSize();
}
vo.addElement(v);
vo.trimToSize();
}
} catch (NullPointerException ex1) {
ex1.printStackTrace();
System.out.println("method testF()'s exception " + ex1.getMessage());
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
try {
if (srs != null) {
srs.close();
}
if (stmt != null) {
stmt.close();
}
if (ucaConn != null) {
// ucaConn.close();
// 因为执行了ucaConn.close()之后,会造成 抛出SQL的异常,于是暂时屏蔽这句话
}
} catch (SQLException sqle) {
sqle.printStackTrace();
System.out.println(sqle.getMessage());
}
}
return vo;
}
/**
* this method is add on 2014-4-9 which is implemented by array instead of vector
* @param sql
* @return
*/
public ArrayList<String[]> arraylistQuery(String sql) {
int numCols = 0;
int rowCount = 0;
String st = null;
ArrayList<String[]> Lo = new ArrayList<String[]>();
try {
stmt = ucaConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
srs = stmt.executeQuery(sql);
rsmd = srs.getMetaData();
numCols = rsmd.getColumnCount(); // 属性数目
srs.last(); // 移到最后一行
rowCount = srs.getRow(); // 得到当前行号也就是记录数
srs.beforeFirst();
for (int i = 0; i < rowCount; i++) {
String[] s0 = new String[numCols];
srs.next(); // java.sql.SQLException: 用尽的 Resultset
for (int j = 0; j < numCols; j++) {
st = srs.getString(j + 1) == null ? "" : srs.getString(j + 1);
s0[j] = st;
}
Lo.add(i,s0);
Lo.trimToSize();
}
} catch (NullPointerException ex1) {
ex1.printStackTrace();
System.out.println(ex1.getMessage());
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
try {
if (srs != null) {
srs.close();
}
if (stmt != null) {
stmt.close();
}
if (ucaConn != null) {
ucaConn.close();
}
} catch (SQLException sqle) {
sqle.printStackTrace();
System.out.println("ArrayList return value exception" + sqle.getMessage());
}
}
return Lo;
}
/**
* @return 获取当前日期
*/
public String getDate() {
String sDate = "";
Calendar cCal = Calendar.getInstance();
int intDay = cCal.get(Calendar.DATE);
int intMonth = cCal.get(Calendar.MONTH) + 1;
int intYear = cCal.get(Calendar.YEAR);
sDate = intYear + "-" + intMonth + "-" + intDay;
return sDate;
}
/**
* @return 获取当前日期时间
*/
public String getDatime() {
String sDatime = "";
Calendar cCal = Calendar.getInstance();
int intDay = cCal.get(Calendar.DATE);
int intMonth = cCal.get(Calendar.MONTH) + 1;
int intYear = cCal.get(Calendar.YEAR);
int intHour = cCal.get(Calendar.HOUR_OF_DAY);
int intMinute = cCal.get(Calendar.MINUTE);
int intSecond = cCal.get(Calendar.SECOND);
sDatime = intYear + "-" + intMonth + "-" + intDay + " " + intHour + ":" + intMinute + ":" + intSecond;
return sDatime;
}
/**
* 对spring jdbc中DriverManagerDataSource进行测试
*/
public void testDS(final String sid) {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("net.ucanaccess.jdbc.UcanaccessDriver");
ds.setUrl(UcanaccessDriver.URL_PREFIX + "\\\\172.16.30.106\\share\\入库检验_be.mdb" + ";newDatabaseVersion=V2003");
ds.setUsername("admin");
ds.setPassword("");
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(ds);
String sql1 = "select * from 检测表 where 编号 = ?";
jt.query(sql1, new Object[] { sid }, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
String sro = rs.getString("检验项目");
System.out.println(sro);
}
});
}
/**
* 入口方法
*/
public static void main(String[] args) throws ClassNotFoundException, SQLException {
try {
AccessTest ex = new AccessTest();
String sd1 = ex.getDatime();
ex.testDS("8666798");
System.out.println(sd1);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}