hibernate 多服务器数据同步问题(支持延迟同步)

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

等……..

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

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

代码说明:
1.新Session 建立
hibernate.cfg.xml 在文件中添加
jdbc:oracle:thin:@192.168.1.114:1521:JCYY

<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
package com.jjm.hibernate;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.hibernate.CallbackException;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.type.Type;

import com.jjm.rlzy.dao.TBDao;

public class TestInterceptor implements Interceptor,Serializable{

static private boolean isConn_b = false ;
static private TBDao tb = new TBDao();
//线程 一分钟 检测连接失败 同步 
static{
    new Thread(new Runnable(){
        public void run() {
            while(true){
                isConn_b = tb.action();
                try {
                    Thread.sleep(60*1000);
                } catch (InterruptedException e) {e.printStackTrace();}
            }
        }
    }).start();
}

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) throws CallbackException {
    Session session = null ;
    try {
        if(isConn_b){
            session =  tb.openSessionb();
            Transaction tr = session.beginTransaction();
            session.update(entity);
            tr.commit();
        }else{
            tb.save(entity,TBDao.UPDATE);
        }
    } catch (Exception e) {
        e.printStackTrace() ;
        tb.save(entity,TBDao.UPDATE);
        isConn_b = false ;
    }finally{
        if(session!=null)session.close();

// 拦截器中 绝对不能有这句 -> SessionManager.closeSession();
}
return false;
}

public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
    Session session = null ;
    try {
        if(isConn_b){
            session =  tb.openSessionb();
            Transaction tr = session.beginTransaction();
            session.save(entity);
            tr.commit();
        }else{
            tb.save(entity,TBDao.INSERT);
        }
    } catch (Exception e) {
        e.printStackTrace() ;
        tb.save(entity,TBDao.INSERT);
        isConn_b = false ;
    }finally{
        if(session!=null)session.close();
    }
    return false;
}

public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
    Session session = null ;
    try {
        if(isConn_b){
            session =  tb.openSessionb();
            Transaction tr = session.beginTransaction();
            session.delete(entity);
            tr.commit();
        }else{
            tb.save(entity,TBDao.DELETE);
        }
    } catch (Exception e) {
        e.printStackTrace() ;
        tb.save(entity,TBDao.DELETE);
        isConn_b = false ;
    }finally{
        if(session!=null)session.close();
    }
}

…………………………..

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值