本文是本人实际开发中遇到,特留文记录。在次我花了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> 中添加
2.异地数据同步失败后动作 TBDao->save() 冻结状态到数据库
3,失败后又成功连接后 (线程实现) TBDao->action()
4.hbn 拦截器 ->Interceptor
后记:
由于一些原因代码写的有些简陋,但功能实现,表达的的意思也还可以(自己有点 ‘买瓜了’哈哈!)。我写出来的目的希望大家能共同进步,这等大家拍砖了 :)
所用到知识点:
一般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()
< property name ="connection.username_b" > jcyy </ property >
< property name ="connection.password_b" > jcyy </ property >
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 ;
}
}
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();
}
}
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 ;
}
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();
}
}
................................
}
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();
}
}
................................
}
后记:
由于一些原因代码写的有些简陋,但功能实现,表达的的意思也还可以(自己有点 ‘买瓜了’哈哈!)。我写出来的目的希望大家能共同进步,这等大家拍砖了 :)