定时更新数据库

   是这样的,公司要求我做一个定时更新数据库的功能,数据的来源是从另外一个服务器上取得,然后取出所有的数据,然后导入另外一个数据库,并且要求每天导入一次,把原来的数据替换掉。
   按照这个需求我去网上查了很多的资料,也找出了几种解决的办法,但是由于技术不够成熟,最终都放弃了,网上的参考方法是:
   1.使用quartz框架,这是纯Java开发的框架,使用起来也很简单,只要自己定义一个Job,创建一个触发器即可。
   2.使用定时作业,这个我不是很清楚,所以首先放弃了。
   3.使用存储过程和Job,由于很久没接触过存储过程,很多知识也记不清了,所以也放弃了
   4.有的建议是用DTSX,说实话到现在我还不知道它是个什么东东。

   这些方法我都去尝试过,但是后来我还是用了自己最笨的方法,用java做了个定时器,定时去调用取数据,和导数据的方法,这个功能是实现了,我测试过也没什么问题,数据也没有丢失的现实。因为还没有正式使用,所以还找不出问题所在,现在我把我的思路和实现的方法给大家看下,如果有问题,请大家指导下,本人现谢过了。
  
   首先由于在导数据的时候,操作员要了解数据是否导入,或者是否已导入成功,要涉及到日志,所以我自己写了一个专门写日志的一个类,代码如下:
    
       public class PrintLog {
     
	
	public PrintLog(){
		
	}
	public static void  writeLog(String log){
		//获取文件缓冲流
		BufferedWriter writer=null;
		try {
			FileWriter fileWriter = new FileWriter("D://log.txt",true);
			 writer=new BufferedWriter(fileWriter);
		//格式化写入时间
			 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			 String writetime=sdf.format(new Date());
			 writer.write(writetime);//写入时间
			 writer.write(log);//写入日志内容
			 writer.newLine();
			 writer.flush();
			 writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
     
   

   接下来我就用jdbc实现的导入数据的功能,由于目前只有一个表。所以实现起来也很简单。但是问题是如果数据量大,会不会有数据重复,溢露的现象呢,这个我也无从分析,反正我用10000条数据测试了下,没有什么问题。然后就是效率的问题,我是每条数据都去执行一次插入,还是去批量的插入。后来我发现jdbc支持批量的插入,所以我选择了批量的插入。
代码如下:
   
     public class DB {
	
	 static int precount=100; 
	
	 public static  Connection getConnect() throws Exception{
		   Class.forName("com.mysql.jdbc.Driver");
		   Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8", "root", "root");
        return conn;        
	  }
	 //插入数据
	 public static int insertObject(List<PoAJ> list){
		 Connection conn=null;
		 PreparedStatement ps=null;
		 try {
			conn=DB.getConnect();
			//关闭自动提交
			conn.setAutoCommit(false);
			//清空数据库
			ps=conn.prepareStatement("truncate poaj");
			//ps.executeUpdate();这里我没用执行,因为一旦出错,没法回滚!
			
			long startTime=System.currentTimeMillis();
			String sql="insert into poaj(ah,name,data)values(?,?,?)";			
			ps=conn.prepareStatement(sql);
			for(int i=0;i<list.size();i++){
				PoAJ p=list.get(i);
			ps.setString(1,p.getAh());
			ps.setString(2,p.getName());
			ps.setInt(3, p.getData());
			ps.addBatch();
			//每precount次就批量处理一次
			}
			//提交
			ps.executeBatch();
		 	conn.commit();
		 	ps.clearBatch();
		 	long endTime=System.currentTimeMillis();
		 	System.out.println("插入数据时间为:"+(endTime-startTime));
		 	return (int)endTime;
		} catch (Exception e) {
			try {
				//如果出现问题就回滚
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
				try {
					if(ps!=null) ps.close();
					if(conn!=null) conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
		 return -1;  
	 }
}
     

     导数据的功能都有了,现在只差如何实现定时去导入数据,所以我用java做了个定时器,在特定是时间执行,这个类我是用timer实现的,它是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。实现的方法如下:
    
      class PickTask{
	
	private Timer timer;
	private String time;//触发时间
	public PickTask(String time){
		timer=new Timer();
		this.time=time;
	}
	
	private TimerTask task=new TimerTask(){
		@Override
		public void run() {
		    	Date date = new Date();
			   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			   String beginDate = sdf.format(date);
			   //截取时间段
			   String beginTime = beginDate.substring(11, 16);
			   System.out.println(beginDate+" "+beginTime);
			  // PrintLog log=new PrintLog();
			   if(beginTime.equals(time)){
				 PrintLog.writeLog("开始取出数据");
				 //这里我自定义了1000条数据
				 
				 List<PoAJ> l=new ArrayList<PoAJ>();
				 long startTime=System.currentTimeMillis();
				for(int i=10000;i<20000;i++){
					PoAJ p=new PoAJ();
					p.setAh(""+i);
					p.setName(""+i);
					p.setData(i);
					l.add(p);
				}
				long endTime=System.currentTimeMillis();
				PrintLog.writeLog("取出数据数量为"+l.size()+" 时间为:"+(endTime-startTime)+"ms");
				 PrintLog.writeLog("开始导入数据");
				 
				 int ret=DB.insertObject(l);
				 
				 if(ret>0){
					 PrintLog.writeLog("导入数据成功,时间为:"+ret+"ms");
				 }else{
					 PrintLog.writeLog("导入数据失败");
				 }
				 //
			   }
			  
		}
		
		
	};
     

     以上做好之后,只需要自定一个时间,然后它就会在定时间去运行。
     功能是现实了,可是我相信还可以更加完善,或者有些漏洞我还没有考虑到的请大虾门指出,或者还有更好的方法借鉴,小弟在此恭候了。

猜你喜欢

转载自jgre.iteye.com/blog/1736469