Java实现Oracle到MySQL的表迁移

来源:互联网 发布:淘宝链接怎么缩短 编辑:程序博客网 时间:2024/06/04 19:19
第一次写博客,希望能帮到别人,同时愿意相互进行一些讨论,互相进步。
    最近在做有关项目的时候,由于服务器数据库被其他人算法读取,导致我读取的时候很慢,于是乎打算将自己需要的表导入到本地的mysql数据库进行处理,刚开始当然是不想写代码,尝试用kettle实现表迁移,但是无奈数据量较大,可kettle内存溢出。痛下决心自己实现。
基本思路就是先从数据库中抽取出数据存储到ResultSet的一个集合中,一个next,存到一个List<List<String>>,为避免内存溢出,设置数组大小超过一个阈值就写入数据库,然后清空又重新读取,在写入。其实这个也是借鉴于kettle的提交Size;
首先是分别建立MySQL和Oracle的链接方法。
Oracle数据连接
public static Connection getConnection(){
Connection conn = null;
String DRIVER="oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:" + "thin:@127.0.0.1:1521:XE";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名
String user = "user";// 用户名,系统默认的账户名
String password = "***";// 你安装时选设置的密码
try {
Class.forName(DRIVER);// 加载数据库驱动程序
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
conn = DriverManager.getConnection(url, user, password);// 获得Connection对象
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
其实mysql方法和Oracle一样的,只是换成mysql的驱动和数据库罢了:
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/spider";
String user = "root";
String password = "***";
然后是抽取数据了:
public static List<List<String>> tableInput() throws FileNotFoundException,
SQLException {
List<List<String>> FindList = new ArrayList<List<String>>();
Connection con = Oracle_con.getConnection();
PreparedStatement pre = null;
ResultSet resultSet = null;
String sql = "SELECT ID,MEDID,COMMODITYNAME,JBBM,JBMC,JZHOSPITALID,DOCTORNAME FROM DISEASE_DRUG_ASSOCIATE_test";
try {
pre = con.prepareStatement(sql);
resultSet = pre.executeQuery();
String[] columu = {"ID","MEDID","COMMODITYNAME","JBBM","JBMC","JZHOSPITALID","DOCTORNAME"};
int i=0;
while (resultSet.next()) {
List<String> minList = new ArrayList<String>();
for(String each:columu){
minList.add(resultSet.getString(each));
}
FindList.add(minList);
i++;
if(i%10000==0){ //设置的每次提交大小为10000
executeManySql(FindList);
FindList.removeAll(FindList);
System.out.println(i);
}
}
executeManySql(FindList);//最后别忘了提交剩余的
return FindList;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
pre.close();// 关闭Statement
} catch (SQLException e) {
e.printStackTrace();
}
try {
con.close();// 关闭Connection
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
executeManySql(FindList)函数如下,因为数据量比较大,所以我设置的每次提交大小为10000,这样就不会内存溢出了。
public static void executeManySql(List<List<String>> FindList) throws SQLException {
Connection con = mysqlConnection.getConnection();
con.setAutoCommit(false);
Statement stat = null;

PreparedStatement pst = (PreparedStatement) con
.prepareStatement("insert into disease_drug_associate_view values (?,?,?,?,?,?,?)");
for (List<String> minList: FindList) {
for(int i=0;i<minList.size();i++){
pst.setString(i+1, minList.get(i));
}
// 把一个SQL命令加入命令列表
pst.addBatch();
}
// 执行批量更新
pst.executeBatch();
// 语句执行完毕,提交本事务
con.commit();
pst.close();
con.close()
;//一定要记住关闭连接,不然mysql回应为too many connection自我保护而断开。
}
同时我还设置了计时的函数,可以看到这个从数据抽取到完成数据迁移的时间。
 public static void main(String[] args) throws FileNotFoundException,
SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SS");
TimeZone t = sdf.getTimeZone();
t.setRawOffset(0);
sdf.setTimeZone(t);
Long startTime = System.currentTimeMillis();
//此段为要放置测取时间的函数
mysqlConnection.executeSql("TRUNCATE table disease_drug_associate_view");
List<List<String>> newDrug = tableInput();

Long endTime = System.currentTimeMillis();
System.out.println("用时:" + sdf.format(new Date(endTime - startTime)));
}
其实用时真不好说,这个和程序本身、抽取数据的主机以及本机的硬盘读取速度有比较大的关系。
最终我抽取的数据是84800000,将近2G的数据,用时:00:57:13:313,五十七分钟还是可以了。

原创粉丝点击