Java实现Oracle到MySQL的表迁移

第一次写博客, 希望能帮到别人, 同时愿意相互进行一些讨论, 互相进步。
最近在做有关项目的时候, 由于服务器数据库被其他人算法读取, 导致我读取的时候很慢, 于是乎打算将自己需要的表导入到本地的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();
		divparedStatement div = null;
		ResultSet resultSet = null;
		String sql = "SELECT ID,MEDID,COMMODITYNAME,JBBM,JBMC,JZHOSPITALID,DOCTORNAME FROM DISEASE_DRUG_ASSOCIATE_test";
		try {
			div = con.divpareStatement(sql);
			resultSet = div.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 {
				div.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;

	divparedStatement pst = (divparedStatement) con
		.divpareStatement("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, 五十七分钟还是可以了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值