技术开发 频道

hibernate多服务器间数据同步



【IT168 技术文档】
本文是本人实际开发中遇到,特留文记录。在次我花了3天的时间解决,这个问题还是点难度的。

所用到知识点:
一般jdk
|-私有属性反射
|-序列化
|-正则表达使用
|-多线程使用
|-dom4j的xml读取
|+hibernate
   |-拦截器
   |-一个Session工厂同时连接不同数据库(本文关键
   |-oracle Blob 存取

等........

需求功能介绍:
 为性能考虑,单一服务器改成集群(每太服务器数据允许在一定时间内保持相步),给出的修改时间短,不过代码持久层比较统一(hibernate 感谢天还好是她! )。网络连接不稳定(铁路内网!)。

完成后效果:
 
当网络连接成功时,多数据库的同步。
   当
网络连接失败时,本地应用程序运用hibernate拦截器拦截正操作对象并记录下操作动作,序列化到本地时局库 z_jcyy_tb 表中。表数据属性为:id,inputdate(记录时间),object(序列对象),action(操作动作)。并安一定时间测试连接。如果成功,读取 z_jcyy_tb 表中数据 反序列化 再同步到 其他数据库中。

代码说明:
1.新Session 建立
  
hibernate.cfg.xml 在文件<session-factory>中添加

<property name="connection.url_b">jdbc:oracle:thin:@192.168.1.114:1521:JCYY</property> <property name="connection.username_b">jcyy</property> <property name="connection.password_b">jcyy</property>

TBDao -> OpenSession()

private static String url_b = null ; private static String use_b = null ; private static String pass_b = null ; private static String dirver_b = null ; static {try { //取得hibernate.cfg.xml逻辑路径,和原来程序关联上 Field field = SessionManager.class.getDeclaredField("CONFIG_FILE_LOCATION"); field.setAccessible( true ); String path = (String) field.get(SessionManager. class ); //通过 dom4j 加载 配置文件 Document docT = new SAXReader().read( TBDao.class.getResourceAsStream(path) ); //正则+xpath读取 在hbn文件中加入的<property name="..._b"> 的属性 String xpath = "/hibernate-configuration/session-factory/property[@name='XPATH_I']" ; Pattern p = Pattern.compile("(XPATH_I)"); Matcher ma = p.matcher(xpath); url_b = DocumentHelper.createXPath( ma.replaceAll("connection.url_b") ).selectSingleNode(docT).getText(); use_b = DocumentHelper.createXPath( ma.replaceAll("connection.username_b")).selectSingleNode(docT).getText(); pass_b = DocumentHelper.createXPath( ma.replaceAll("connection.password_b")).selectSingleNode(docT).getText(); dirver_b = DocumentHelper.createXPath( ma.replaceAll("connection.driver_class")).selectSingleNode(docT).getText(); } catch (Exception e) {e.printStackTrace();}} //利用hbn的SessionFactory得到 openSession(Connection); 打开异地数据库连接。 //利用私有反射得到 加载完成的SessionFactory public Session openSessionb(){ try { Class.forName(dirver_b); Connection conn = DriverManager.getConnection(url_b,use_b,pass_b); Field[] fields = SessionManager.class.getDeclaredFields(); Field field = null ; for(int i=0;i<fields.length;i++){ if( SessionFactory.class.equals( fields[i].getType() ) ) field = fields[i]; } field.setAccessible(true); SessionFactory sessionFactory = (SessionFactory) field.get(SessionManager.class ); return sessionFactory.openSession(conn); } catch (Exception e) { System.out.println("--没有连接到总服务(openSessionb)--"); return null ; } }

2.异地数据同步失败后动作  TBDao->save() 冻结状态到数据库

public void save(Object obj,String action) { Session session = null ; try { session = SessionManager.currentSession(null,null); Transaction tr = session.beginTransaction(); ZJcyyTb zj = new ZJcyyTb(); zj.setAction(action); zj.setInputdate(new Date()); session.save(zj); session.flush(); session.refresh(zj,LockMode.UPGRADE); //oracle Blob数据持久 请参考-->序列化和反序列化对象到 数据库 zj.setObject( new ObjectConvert().ObjectToBlob(obj) ); tr.commit(); } catch (Exception e) { e.printStackTrace(); }finally{ if(session!=null&& session.isOpen() )session.close(); } }

3,失败后又成功连接后 (线程实现) TBDao->action()

public int isSql(){ int is_count = 0 ; Session session = null ; try { //得到本地Session 查看是否有连接失败后序列动作被保存 session = SessionManager.currentSession(null,null); Transaction tr = session.beginTransaction(); Connection conn = session.connection(); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("select count(*) from z_jcyy_tb"); rs.next(); is_count = rs.getInt(1); tr.commit(); } catch (Exception e) { e.printStackTrace(); }finally{ if(session!=null&& session.isOpen() )session.close(); } return is_count ; } public boolean action(){ int isSql = 0 ; ObjectConvert oc = new ObjectConvert(); Session session = null ; Session session_b = null ; try { //有失败连接动作后尝试 远程数据库 if( (isSql=isSql())>0 ){ session = SessionManager.currentSession(null,null); //远程数据库连接 //如果成功连接:z_jcyy_tb表中数据同步到其他数据库中 session_b = openSessionb(); if(session_b!=null){ Transaction tr_b = session_b.beginTransaction(); Transaction tr = session.beginTransaction(); Query qu = session.createQuery(" from ZJcyyTb t order by t.inputdate"); for(int i=0;i<=isSql/10;i++){ qu.setFirstResult(i*10); qu.setMaxResults(10); List list = qu.list(); for(Iterator it=list.iterator();it.hasNext();){ ZJcyyTb tb = (ZJcyyTb)it.next(); Object obj = null ; obj = oc.BlobToObject(tb.getObject(),obj); if(obj!=null){ String action = tb.getAction(); if(action.equals( TBDao.DELETE )){ session_b.delete(obj); } if(action.equals( TBDao.INSERT )){ session_b.save(obj); } if(action.equals( TBDao.UPDATE )){ session_b.update(obj); } } session.delete(tb); tr.commit(); } } tr_b.commit(); } } return true ; } catch (Exception e) { System.out.println("--没有连接到总服务(action)--"); }finally{ if(session_b!=null&&session_b.isOpen())session_b.close(); if(session!=null&& session.isOpen() )session.close(); SessionManager.closeSession(); } return false ; }
4.hbn 拦截器 ->Interceptor


0
相关文章