在開始學習XML和資料庫編程時,大家都對一大堆的文檔和資料,無從入手。作者在工作中,正好要用到了這些,就手頭的一個程式進行整理。其功能很簡單,得用java語言,從access資料庫中,把一些資料匯入到SQL資料庫中。
需求:
原Access資料庫表結構:
表:production
產品型號 字串型………產品編號
零件圖號 字串型……….零件編號
圖號 字串型……….工具編號
SQL資料表結構:
Project 產品表
Id int 標識
Number… varchar64 編號
Product 零件表
Id int 標識
pid int 產品標識號(與project表中的id相關聯)
Number… varchar64 編號
Componenttype 與零件對應的生產工具表
Id int 標識
aid int 零件標識(與product表中的id關聯)
Number… varchar64 編號
要求把原來的編號分別放到下面的SQL三個表格中,並用id關聯起來。
考慮到資料庫連接可能有變化,決定使用xml來配置資料連線。Dbs.xml檔案內容如下:
<?xml version="1.0" encoding="GBK"?>
<dbcopy>
<source>
<class>sun.jdbc.odbc.JdbcOdbcDriver</class>
<url>jdbc:odbc:asrs</url>
<user>""</user>
<password>""</password>
</source>
<dest>
<class>com.microsoft.jdbc.sqlserver.SQLServerDriver</class>
<url>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=vxms</url>
<user>vxms</user>
<password>vxms</password>
</dest>
</dbcopy>
檔案ConnPara.java,表示以類形式表示的資料庫連接參數。
public class ConnPara
{
String dbClass=null;
String url=null;
String username=null;
String password=null;
public ConnPara() { }
public ConnPara(String pdbClass,String purl,String pusername,String ppassword)
{
dbClass=pdbClass;
url=purl;
username=pusername;
password=ppassword;
}
public String getDbClass(){return dbClass;}
public String getUrl(){return url;}
public String getUsername(){return username;}
public String getPassword(){return password;}
public void setDbClass(String str){ dbClass=str;}
public void setUrl(String str){ url=str;}
public void setUsername(String str){username=str;}
public void setPassword(String str){password=str;}
}
檔案DbXmlParser.java封裝了對xml檔案的操作。
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;
public class DbXmlParser
{
static String xmlfile;
public DbXmlParser(String filename)
{
xmlfile=filename;
}
public static Element loadDocument()
{
try
{
//工廠
DocumentBuilderFactory dcfactory=DocumentBuilderFactory.newInstance();
//文檔構造器
DocumentBuilder db=dcfactory.newDocumentBuilder();
//構造的文檔
Document doc=db.parse(xmlfile);
//根項目
Element root=doc.getDocumentElement();
return root;
}catch( ParserConfigurationException e){
System.out.println("ParserConfigurationException");
e.printStackTrace();
}catch(IOException e) {
System.out.println("IOException ");
e.printStackTrace();
}catch(SAXException e) {
System.out.println("SAXException ");
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
return null;
}
public ConnPara getSource()
{
Element root=loadDocument();
if( root==null) { return null; }
NodeList nodes=root.getElementsByTagName("source");
if(nodes.getLength()>0)
{
Node node=nodes.item(0);
String connclass=getChildElementValue(node,"class");
String url=getChildElementValue(node,"url");
String username=getChildElementValue(node,"user");
String password=getChildElementValue(node,"password");
return new ConnPara(connclass,url,username,password);
}
return null;
}
public ConnPara getDest()
{
Element root=loadDocument();
if( root==null) return null;
NodeList nodes=root.getElementsByTagName("dest");
if(nodes.getLength()>0)
{
Node node=nodes.item(0);
String connclass=getChildElementValue(node,"class");
String url=getChildElementValue(node,"url");
String username=getChildElementValue(node,"user");
String password=getChildElementValue(node,"password");
return new ConnPara(connclass,url,username,password);
}
return null;
}
//得到子項目的值
private String getChildElementValue(Node node,String subTagName)
{
String returnString = "";
if(node != null)
{
NodeList children = node.getChildNodes();
for(int innerLoop = 0; innerLoop < children.getLength(); innerLoop++)
{
Node child = children.item(innerLoop);
if(child == null || child.getNodeName() == null || !child.getNodeName().equals(subTagName))
continue;
Node grandChild = child.getFirstChild();
if(grandChild.getNodeValue() != null)
return grandChild.getNodeValue();
}
}
return returnString;
}
}
檔案DbInput.java則是真正的資料拷貝部分:
import java.sql.*;
public class DbInput
{
Connection src=null;
Connection dest=null;
Connection connformax=null;
ConnPara srcPara;
ConnPara destPara;
public DbInput(){}
public void dbInit()
{
DbXmlParser xmlparser=new DbXmlParser("dbs.xml");
srcPara=xmlparser.getSource();
destPara=xmlparser.getDest();
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver" );
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
src = DriverManager.getConnection( srcPara.getUrl(), srcPara.getUsername(),srcPara.getPassword());
dest =DriverManager.getConnection( destPara.getUrl(), destPara.getUsername(),destPara.getPassword());
connformax= DriverManager.getConnection( destPara.getUrl(), destPara.getUsername(),destPara.getPassword());
}
//捕獲載入驅動程式異常
catch ( ClassNotFoundException cnfex ) {
System.err.println( "裝載 JDBC/ODBC 驅動程式失敗。" );
cnfex.printStackTrace();
System.exit( 1 ); // terminate program
} catch ( SQLException ex )
{
System.err.println( "串連失敗" );
ex.printStackTrace();
System.exit( 1 ); // terminate program
}
}
public void copyproduct()
{
Statement st=null;
ResultSet rset=null;
String sqlstr;
try {
//執行SQL語句
String query = "select * from production";
st = src.createStatement();
rset = st.executeQuery(query);
int pid,ljid,cid,ciid;
while(rset.next())
{
String pnumber=rset.getString(1);
String ljnumber=rset.getString(2);
String cnumber=rset.getString(3);
//插入到產品表
pid=getIdfromNumber("project","number",pnumber);
if(pid==0) //插入一條新記錄
{
pid=getMax("project");//System.out.println(pid);
sqlstr="Insert into project(id,number) values("+pid+",'"+pnumber+"')";
execute(destPara,sqlstr);
}
//插入到零件表
ljid=getIdfromNumber("product","number",ljnumber);
if(ljid==0) //插入一條新記錄
{
ljid=getMax("product");
sqlstr="Insert into product(id,pid,number) values("+ljid+","+pid+",'"+ljnumber+"')";
execute(destPara,sqlstr);
}
//插入工具表
cid=getIdfromNumber("componenttype","number",cnumber);
if(cid==0) //插入一條新記錄
{
cid=getMax("componenttype");
sqlstr="Insert into componenttype(id,aid,number) values("+cid+","+ljid+",'"+cnumber+"')";
execute(destPara,sqlstr);
}
}
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
}
}
protected boolean alreadyin(String tname,String colname, String value)
{
int result;
ResultSet rst=null;
try {
//執行SQL語句
String query = "select "+colname+" from "+tname+" where "+colname+"='"+value+"'";
Statement statement = connformax.createStatement();
rst = statement.executeQuery( query );
if(rst.next())
{
statement.close();
rst.close();
return true;
}
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
return false;
}
return false;
}
protected int getIdfromNumber(String tname,String colname, String value)
{
int result;
ResultSet rst=null;
try {
Connection conn= DriverManager.getConnection( destPara.getUrl(), destPara.getUsername(),destPara.getPassword());
String query = "select id,"+colname+" from "+tname+" where "+colname+"='"+value+"'";
System.out.println(query);
Statement statement = conn.createStatement();
rst = statement.executeQuery( query );
if(rst.next())
{
return rst.getInt("id");
}
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
return 0;
}
return 0;
}
/**
* 得到某個表中的最大的id號
*/
protected int getMax(String tname)
{
int result;
ResultSet rst=null;
try {
//執行SQL語句
String query = "select Max(id) from "+tname;
Statement statement = connformax.createStatement();
rst = statement.executeQuery( query );
if(rst.next())
{
return rst.getInt(1)+1;
}
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
return 0;
}
return 1;
}
/**
* 執行某一段sql語句
*/
public static void execute(ConnPara connpara,String stmt) throws SQLException
{
Connection conn=null;
PreparedStatement ps = null;
try {
conn=DriverManager.getConnection( connpara.getUrl(), connpara.getUsername(), connpara.getPassword());
System.out.println(stmt);
ps = conn.prepareStatement(stmt);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
if (ps!=null) ps.close();
if (conn!=null)conn.close();
}
}
public static void main(String argc[])
{
DbInput copydb=new DbInput();
copydb.dbInit();
copydb.copyproduct();
}
}
問題:
1) access資料庫不能直接由jdbc讀寫,解決辦法是先把access配置在ODBC中,然後再通過ODBC來操作access資料庫。
2) 執行時找不到com.microsoft.jdbc.sqlserver.SQLServerDriver類,這是因為在運行這個類時,要下載微軟的jdbc包,這個包中有三個檔案: msbase.jar,mssqlserver.jar,msutil.jar,把這三個檔案包含進去,就不會有問題了。