spring下hibernate多数据库解决方案,以及跨库事务的尝试(已合并)
这个我自己系统配置的一部分,系统会解析他,从而知晓究竟存在多少个sessionFactory,item's XmlNode中的id可以理解会托管客户的客户单位<o:p></o:p>
编号,当然,这个配置完全可以忽略,直接从ApplicationContext中一样可以获取到这样的信息<o:p></o:p>
在客户登陆的时候,系统要记录下该客户所属托管单位,然后通过上面的id找到bean's name ,最后获取这个sessionFactory,托管单位信息一般<o:p></o:p>
都是个编号而已跟己方系统的托管用户管理相结合,一般是保存这个编号在session里面,也可以象asp.net一样,记录在安全凭证里,还不知道JAVA方面有没有类似实现,个人认为asp.net这个方法很值得采用,虽然MS号称安全系数+++++这个观点值得怀疑<o:p></o:p>
<o:p> </o:p>
首先建立一个类,HibernateSupport ,存放当前请求线程所需sessionFactoryafterPropertiesSet方法中那些检查代码<o:p></o:p>
然后 ,ant打包就可以了,如果不想修改spring的代码,也可以单独把这几个类提出来另建jar包,我是单独提出来新建的,比如HibernateTransactionManager我改名成CHibernateTransactionManager,其他类似,但是包名必须是org.springframework.orm.hibernate3 ,谁也不想这么做,可是谁让sessionFactoryUtils中一个closexxxx方法没定义成public了??<o:p></o:p>
如果想变更sessionFactoryUtils,奉劝算了吧..<o:p></o:p>
然后可以做测试了,首先,部署测试的dao和service,先是事务部署<o:p></o:p>
<bean id="transactionManager" ref="transactionManager"/> <property name="transactionAttributeSource"><ref local="transres"/></property> </bean> <bean ref="transactionInterceptor"/> </bean><bean id="personDao" name="code">public class PersonDaoImpl extends CHibernateDaoSupport implements PersonDao; public class PersonServiceImpl implements PersonService; public class DepartDaoImpl extends CHibernateDaoSupport implements DepartDao; public class DepartServiceImpl implements DepartService;
public class DepartServiceImpl implements DepartService { private DepartDao dao; private PersonService service; .............................. public void executeTest(Depart depart,Person person) { dao.save(depart); HibernateSupport.switchFactory("test"); service.save(person); HibernateSupport.restoreFactory(); } ..............................
private static class LazyTransactionStatus{private java.util.List transliat;private int transnum;//代表未提交事务数量public LazyTransactionStatus(){transliat= new java.util.ArrayList();transnum=0;}public void newLazy(){transnum++;}public void push(TransactionStatus trasobj){objmap.add(trasobj);}public void removeLazy(TransactionStatus trasobj){transnum--;}public boolean canCommit(){if (transnum<1){return true;}elsereturn false;}public java.util.List getTransactionObjs(){return transliat;}}}
public final boolean isCommit(TransactionStatus status){if (lazytrace.get()!=null){LazyTransactionStatus lazystatus = (LazyTransactionStatus)lazytrace.get();lazystatus.removeLazy(status);return lazy.canCommit();}return true;}protected void begin(Object transaction, TransactionDefinition definition){doBegin(transaction,definition);LazyTransactionStatus lazystatus = null;if (lazytrace.get()==null){lazystatus = new LazyTransactionStatus();lazytrace.set(lazystatus);}else{lazystatus = (LazyTransactionStatus)lazytrace.get();}lazystatus.newLazy();}public final void registerTraceStatus(TransactionStatus status){LazyTransactionStatus lazystatus = null;if (lazytrace.get()==null){lazystatus = new LazyTransactionStatus();lazytrace.set(lazystatus);}else{lazystatus = (LazyTransactionStatus)lazytrace.get();}lazystatus.push(status);}
public final void commit(TransactionStatus txstatus) throws TransactionException {this.registerTraceStatus(txstatus);if (this.isCommit(txstatus)){int error = 0;LazyTransactionStatus lazystatus = (LazyTransactionStatus)lazytrace.get();List statuslist = lazystatus.getTransactionObjs();for (int i=0;i<statuslist.size();i++){try{TransactionStatus status = (TransactionStatus)statuslist.get(i);if (status.isCompleted()) {error++;continue;//throw new IllegalTransactionStateException(//"Transaction is already completed - do not call commit or rollback more than once per transaction");}DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;if (defStatus.isLocalRollbackOnly()) {if (defStatus.isDebug()) {logger.debug("Transactional code has requested rollback");}processRollback(defStatus);error++;continue;}if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {if (defStatus.isDebug()) {logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");}processRollback(defStatus);// Throw UnexpectedRollbackException only at outermost transaction boundary// or if explicitly asked to.if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {//throw new UnexpectedRollbackException(//"Transaction rolled back because it has been marked as rollback-only");error++;continue;}continue;}processCommit(defStatus);}catch (Exception ex){error++;ex.printStackTrace();continue;}}lazytrace.set(null);if (error>0)throw new IllegalTransactionStateException("Not commit all transaction");}}