- 浏览: 25291 次
- 性别:
- 来自: 重庆
文章分类
最新评论
-
guanfj:
了解一下,你以目前的修改的方案做的系统目前还在运行着吗?
Hibernate自定义表单完全解决方案(无需重置SessionFactory) -
zhushaolong:
问一下你用的hibernate的版本是多少啊?我怎么没有在Pe ...
Hibernate自定义表单解决方案补遗 -
firmgoal:
hantsy 写道为什么还生成类和映射文件。。。
hibern ...
Hibernate自定义表单完全解决方案(无需重置SessionFactory) -
bribin:
不得不对LZ说一句,你太牛了,怎么连Configuration ...
Hibernate自定义表单完全解决方案(无需重置SessionFactory) -
onlydo:
还有下文么?我对这个很感兴趣阿。用jpa的话要怎么实现?
另外 ...
Hibernate自定义表单完全解决方案(无需重置SessionFactory)
开发目的:一个协同平台项目,多托管用户,单门户系统,每个托管用户对应一个单一数据库,要求根据登陆用户的单位信息,自动选择操作数据库;同时,涉及跨库操作(比如跨库查询,跨库单据发送);同时事务处理必须支持这种多数据库模式,支持一些逻辑性不强的跨库事务,比如一些数据的发送和接收等<o:p></o:p>
当然,如果说跨库操作只涉及到数据的发送和接受的话,也可以通过构建专门web service以及通信线程来处理,<o:p></o:p>
开发环境: tomcat4.1,webwork<st1:chsdate month="12" islunardate="False" day="30" year="1899" w:st="on" isrocdate="False">2.2.4</st1:chsdate>,spring2.0.4,hibernate3.1,osworkflow2.8,mysql5.0.19 由于正式发布的应用服务器是weblogic8.1,所以没有采用jdk5环境以及struts2<o:p></o:p>
准备:<o:p></o:p>
问题一 由于有跨库操作,而且这种跨库操作无法预知,有的跨库操作完全是在逻辑运行中决定的,比如A托管用户或则C、D向B托管用户发了订单 ,B回复,这个回复是根据订单发送者来说的,具体到后台操作,是无法事先预知针对具体哪个后台物理数据库操作的.所以,也就是说,存在在业务执行过程中切换数据库的情况,传统的到注入设置dao类 sessionFactory、靠filter以及Interceptor设置线程安全的sessionFactory都无法完全达到设计目的<o:p></o:p>
问题二 事务,本来,我打算用JtaTransactionManager的,除了JtaTransactionManager,在开始时也实在没想到什么好的办法, 难道,JtaTransactionManager是唯一选择么?<o:p></o:p>
步骤:<o:p></o:p>
、 因为问题一,所以系统在资源方面是多sessionFactory并存的方式,也就是多少个托管用户多少个sessionFactory,当然,事实上,这种应用型项目本身并发访问量不会太高(什么,很高么,总比不过广告联盟吧,哈哈).不用担心多了几个sessionFactory会对系统或则数据库造成多大影响.<o:p></o:p>
<o:p>
- <bean id="mitDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
- <property name="driverClass">
- <value>com.mysql.jdbc.Driver</value>
- </property>
- <property name="jdbcUrl">
- <value>jdbc:mysql://127.0.0.1:3306/mitflow</value>
- </property>
- <property name="user">
- <value>root</value>
- </property>
- ...........................
- </bean>
- <bean id="mitSessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="mappingResources">
- ..................................
- </props>
- </property>
- <property name="dataSource">
- <ref local="mitDataSource" />
- </property>
- </bean>
然后复制,粘贴,修改jdbcUrl,象网站编辑一样..
假设,我配置了两个sessionFatory ,一个是mitSessionFactory,一个是testSessionFactory,如下:
- <hibernatesupport>
- <item id="mit" bean="mitSessionFactory"/>
- <item id="test" bean="testSessionFactory"/>
- < hibernatesupport>
这个我自己系统配置的一部分,系统会解析他,从而知晓究竟存在多少个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 ,存放当前请求线程所需sessionFactory- public class HibernateSupport {
- public static final String HIBERNATE_SESSIONIDKEY = "com.mit.hibernatesupport.factory.id";
- private static final Logger logger = Logger.getLogger(HibernateSupport.class);
- private static ApplicationContext applicationContext ;
- private static boolean singleSession=true;
- private static Map factorybeanset;
- private static ThreadLocal switchhistory;//在切换不同sessionFactory的时候用到
- private static ThreadLocal idset;//记录当前默认的托管用户id,在实际使用中,这个是可以取消掉的
- private static ThreadLocal curfactory;////当前正在使用的sessionFactory
- private static ThreadLocal trace;//一个sessionFactory集合,用来记录这次线程调用了那些sessionFactory
- static
- {
- idset = new ThreadLocal();
- curfactory = new ThreadLocal();
- trace = new ThreadLocal();
- switchhistory = new ThreadLocal();
- }
- /**
- * set current sessionfactory for the Request
- * @param ServletContext
- * @param the factory's id defined in courser.xml
- */
- public static synchronized void setCurrent(ServletContext context,Object id)
- {
- if (idset.get()==null)
- {
- idset.set(id);
- if (factorybeanset.containsKey(id))
- {
- if (applicationContext==null)
- {
- applicationContext =
- WebApplicationContextUtils
- .getWebApplicationContext(context);
- }
- curfactory.set((SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id)));
- putTrace(idset.get(),(SessionFactory)curfactory.get());
- }
- }
- }
- /**
- * put the sessionfactory to tracemap
- * @see COPenSessionInViewFilter release sessionfactory in tracemap
- * @param the factory's id defined in courser.xml
- * @param hibernate's sessionfactory
- */
- private static void putTrace(Object id ,SessionFactory factory)
- {
- Map tracemap = null;
- if (trace.get()==null)
- {
- tracemap = new HashMap();
- trace.set(tracemap);
- }
- else
- {
- tracemap = (Map)trace.get();
- }
- if (!tracemap.containsKey(id))
- {
- tracemap.put(id, factory);
- }
- }
- /**
- * switch current sessionfactory
- * @param the factory's id defined in courser.xml
- */
- public static synchronized void swtichFactory(Object id)
- {
- if (!idset.get().equals(id) )
- {
- if (factorybeanset.containsKey(id))
- {
- SessionFactory oldfactory = (SessionFactory)curfactory.get();
- SessionFactory newfactory = (SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id));
- curfactory.set(newfactory);
- pushHistory(oldfactory);
- putTrace(id,newfactory);
- bindSessionFactory(newfactory);
- }
- }
- }
- /**
- * restore sessionfactory from queue of switchhistory
- */
- public static synchronized void restoreFactory()
- {
- SessionFactory factory = popHistory();
- if (factory!=null)
- {
- curfactory.set(factory);
- }
- }
- /**
- * push old sessionfactory to swithhistory after swtichFactory
- * @param hibernate's sessionfactory
- */
- private static void pushHistory(SessionFactory sessionfactory)
- {
- LinkedList list = null;
- if (switchhistory.get()==null)
- {
- list = new LinkedList();
- switchhistory.set(list);
- }
- else
- {
- list = (LinkedList)switchhistory.get();
- }
- list.add(0,sessionfactory);
- }
- /**
- * pop sessionfactory in queue
- */
- private static SessionFactory popHistory()
- {
- if (switchhistory.get()!=null)
- {
- LinkedList list = (LinkedList)switchhistory.get();
- if (list.size()>0)
- {
- SessionFactory factory = (SessionFactory)list.getFirst();
- list.removeFirst();
- return factory;
- }
- }
- return null;
- }
- public static Map getTraceMap()
- {
- if (trace.get()!=null)
- {
- return (Map)trace.get();
- }
- return null;
- }
- public static SessionFactory getCurrentFactory()
- {
- return (SessionFactory)curfactory.get();
- }
- public static synchronized void release()
- {
- idset.set(null);
- curfactory.set(null);
- switchhistory.set(null);
- trace.set(null);
- }
- /**
- * °ó¶¨sessionFactoryµ½springµÄ×ÊÔ´¹ÜÀí
- * @param hibernate's sessionfactory
- */
- private static synchronized boolean bindSessionFactory(SessionFactory sessionFactory)
- {
- boolean participate=false;;
- if (singleSession) {
- // single session mode
- if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
- // Do not modify the Session: just set the participate flag.
- participate = true;
- }
- else {
- logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
- Session session = getSession(sessionFactory);
- if (!TransactionSynchronizationManager.hasResource(sessionFactory))
- {
- TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
- }
- }
- }
- else {
- // deferred close mode
- if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
- // Do not modify deferred close: just set the participate flag.
- participate = true;
- }
- else {
- SessionFactoryUtils.initDeferredClose(sessionFactory);
- }
- }
- return participate;
- }
- //see SessionFactoryUtils
- private static Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
- Session session = SessionFactoryUtils.getSession(sessionFactory, true);
- FlushMode flushMode = FlushMode.COMMIT;
- if (flushMode != null) {
- session.setFlushMode(flushMode);
- }
- return session;
- }
- public static synchronized void initSessionFactory(Map res,Class loadclass)
- {
- factorybeanset =res;
- }
- }
- if (idset.get()==null)
- {
- idset.set(id);
- if (factorybeanset.containsKey(id)) //factorybeanset包含的就是我自己系统配置中那一部分,key就是id,,value就是sessionFactory 在spring环境中的beanName
- {
- if (applicationContext==null)
- {
- applicationContext =WebApplicationContextUtils.getWebApplicationContext(context);
- }
- curfactory.set((SessionFactory)applicationContext.getBean((String)factorybeanset.get(id)));//设置当前的sessionFactory
- putTrace(idset.get(),(SessionFactory)curfactory.get());//put到当前线程的一个记录集
- }
- }
多sessionFactory好做,配置在spring或则单独拿出来处理都可以,但是spring的HibernateDaoSupport 必须绑定一个sessionFactory,当然,我们完全可以写一个自己的HibernateDaoSupport ,但是既然用了spring的事务管理而又不想多花时间,还是将就改改用吧
- private SessionFactory sessionFactory;
- publicvoid setSessionFactory(SessionFactory sessionFactory) {
- this.sessionFactory = sessionFactory;
- }
去掉HibernateAccessor 和HibernateTransactionManager中的上述两段代码,当然,也别忘了毙掉两个类中的<o:p></o:p>
afterPropertiesSet方法中那些检查代码<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"
- class="com.mit.web.hibernate.CHibernateTransactionManager"/>
- <bean id="transres" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
- <property name="properties">
- <props>
- <prop key="load*">PROPAGATION_REQUIRED,readOnly<!---->prop>
- <prop key="save*">PROPAGATION_REQUIRED<!---->prop>
- <prop key="delete*">PROPAGATION_REQUIRED<!---->prop>
- <prop key="find*">PROPAGATION_REQUIRED,readOnly<!---->prop>
- <prop key="query*">PROPAGATION_REQUIRED,readOnly<!---->prop>
- <prop key="create*">PROPAGATION_REQUIRED<!---->prop>
- <prop key="set*">PROPAGATION_REQUIRED,readOnly<!---->prop>
- <prop key="execute*">PROPAGATION_REQUIRED<!---->prop>
- <!---->props>
- <!---->property>
- <!---->bean>
- <bean id="transactionInterceptor" class=
评论
延迟事务,就是将事务延后提交,延迟的时间由事务管理器掌握。在我的系统中,只有跨库操作涉及到延迟提交,针对这种操作,我设计了一个基本的执行模型。就是如果一个逻辑中存在多个事务,将全部放到逻辑执行完以后提交,那么,既然如此,开始吧
PlatformTransactionManager是spring平台相关事务,比如HibernateTransactionManager都是继承于此类,为了达到延迟提交的目的,可以在AbstractPlatformTransactionManagershang上做修改达到目的
首先,说一下在spring中,通常的一个事务流程,
流程如下:初始化Transaction B,如果发现前面有其他Transaction ,比如 Transaction A,那么挂起TransactionA ,然后启动事务 ,当逻辑执行完后 ,commit,恢复挂起事务A,然后清除同步对象以及其他资源,如果执行发生异常,当然,异常发生后 rollback
延迟提交的设计思想是将事务都暂存在一个threadlocal的LIST里面,等逻辑执行完以后,再统一提交,那么首先在AbstractPlatformTransactionManager中设置一个threadlocal对象
private ThreadLocal lazytrace = new ThreadLocal();
LazyTransactionStatus用来管理需要延迟提交的事务
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; } else return false; } public java.util.List getTransactionObjs() { return transliat; } } }
这就是local对象的存储内容.translist存放当前执行中的TransactionStatus实例
TransactionStatus顾名思义,事务状态,包含了事务、挂起资源等一系列信息
然后以事务提交为例
然后在AbstractTransactionManager增加如下两个方法
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); }
begin ,当一个事务开始时,将LazyTransactionStatus的transnum+1,表示又多了个刚开始,还未提交的事务
registerTraceStatus发生在commit的时候,注册这个事务到LazyTransactionStatus,同时,
注意 transnum表示的是未提交事务数量,所以当事务管理器执行commit表示要提交一个事务后,transnum将减一,如果减一后发现transnum<1,表示所有事务都提交了,那么,将所有事务提交。否则,不提交,继续等待...
关系如下:
begin->transnum+1 表示新事务诞生
registerTraceStatus(发生在commit的时候)->将准备提交的TransStatus放到LazyTransactionStatus,是的,这个事务要提交了,来吧,先注册一下
紧接着
isCommit()->将transnum-1,如果发现transnum小于1 ,表示闹够了,可以都提交滚蛋了
注意 ,transnum与LazyTransactionStatus的translist的链表长度在执行commit的时候是反方向发展的 一个增,一个减
好了,首先是注册事务数量,不用管了,在事务开始时begin方法它自己会调用了,
然后是修改AbstractPlatformTransactionManager的commit方法
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"); } }
this.registerTraceStatus(txstatus);//事务提交了,成了嫌疑犯,拖到threadlocal的LazyTransactionStatus监狱里面先关起来
if (isCommit()) //看看监狱的事务是不是满了,如果满了,就可以全放了
LazyTransactionStatus lazystatus = (LazyTransactionStatus)lazytrace.get();
List statuslist = lazystatus.getTransactionObjs();
for (int i=0;i<statuslist.size();i++)
{
........
processCommit(defStatus);
//看来真的满了,都放了吧
回滚道理是一样的,不过不用判断了,直接全部放出来让他们滚吧
当然,目前这个实现只是个模型,真要实际应用,还需要做进一步封装,实际做,我用了OpenSessionInViewFilter,我已经做过测试,测试了了OpenSessionInViewFilter中singleSession为true和false两种情况,测试都通过了,呵呵
事务配置如下:
<bean id="transactionManager" class="com.mit.web.hibernate.CHibernateTransactionManager"/> <bean id="transres" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"> <property name="properties"> <props> <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="create*">PROPAGATION_REQUIRED</prop> <prop key="set*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="execute*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributeSource"><ref local="transres"/></property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"><value>*Service</value></property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> <bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"> <property name="transactionInterceptor" ref="transactionInterceptor"/> </bean>
我把事务配置在service层,事务管理采用的是我修改后的HibernateTransactionManager ,他不在要求sessionFactory的注入了
以下是测试的dao类和service类配置
<bean id="personDao" class="com.mit.web.action.PersonDaoImpl"/> <bean id="personService" class="com.mit.web.action.PersonServiceImpl"> <property name="personDao"> <ref bean="personDao"/> </property> </bean> <bean id="departDao" class="com.mit.web.action.DepartDaoImpl"/> <bean id="departService" class="com.mit.web.action.DepartServiceImpl"> <property name="personService"> <ref bean="personService"/> </property> <property name="departDao"> <ref bean="departDao"/> </property> </bean>
具体代码不写了,大概如下:
public class PersonDaoImpl extends CHibernateDaoSupport implements PersonDao; public class PersonServiceImpl implements PersonService; public class DepartDaoImpl extends CHibernateDaoSupport implements DepartDao; public class DepartServiceImpl implements DepartService;
测试代码的目的是将两个实体类分别存放到mit和test库,假设默认用户是mit这个托管库的,这个方法就写在DepartServiceImpl类里面
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(); } ..............................
上面代码中将depart对象存到mit库,而将person对象存到test库中.
事务 事务 ,没看见特别事务设置? 其实事务已经在运行了
如前面配置,事务我配置在了service层,那么当executeTest执行时,会启动针对mit库的事务(前面我们改了HibernateTransactionManager的sessionFactory获取方式),
dao.save(depart);//然后保存depart到mit库
HibernateSupport.switchFactory("test");//切换库到test
service.save(person);//调用personService的save方法,这也是个service,所以也会产生一个事务,而此时HibernateSupport.getCurrentFactory返回的sessionFactory已经是test库的了,所以,spring事务管理发现上下文中并没有针对test的事务,于是,会重新启动一个新的事务,这个service.save(person);方法执行完后,这个事务将会提交
HibernateSupport.restoreFactory();//切换回默认数据库
整个方法执行完后,针对mit的事务将会被提交
[color=green]如果service.save(person);发生异常,这两个事务就会被提交,一个简单跨库事务控制完成[color=green]
但是,问题也随之而来,如果在 HibernateSupport.restoreFactory();后,又进行了一些逻辑操作,那么发生异常时,而由于 service.save(person);这个事务已经被提交,也就是说,针对test的事务已经提交不会回滚了,这是个非常严重的问题。。
其实,也有解决方法,就是延迟提交,具体实现方式以后讲述
就像command pattern的undo,而且还有一个MEMENTO,入在log里.
dist transaction的机制应该差不多,只是加了个message queue
以下存属个人理解:
其实JtaTransactionManager做的正是这一点, 在spring中通过TransactionSynchronizer来实现的:service.save()并不会commit,而是将当前Transaction放入一个ThreadLocal的Transaction list里,到结束时一起处理.
楼主代码不错,适合于写框架,呵呵
相关推荐
而Hibernate则是一个全功能的对象关系映射(ORM)解决方案,它允许开发者以面向对象的方式来处理数据库操作。 Spring与Hibernate的整合可以带来很多好处,例如简化配置、提高代码的可维护性和可测试性等。接下来,...
Struts2 是一个基于MVC(Model-View-Controller)设计模式的Web框架,它是Struts 1.x和WebWork的合并版本,提供更强大、更灵活的控制层解决方案。Struts2的核心是Action,它处理用户请求,并通过Interceptor(拦截器...
总结来说,这个实例展示了如何利用Struts2处理用户交互,Spring进行依赖管理和流程整合,Hibernate负责数据持久化,以及Jbpm实现业务流程管理,形成一个完整的企业级应用解决方案。通过对这些技术的深入理解和实践,...
总结,osWorkflow2.8与Spring和Hibernate的整合,能够为开发人员提供一套完整的业务流程解决方案,帮助他们快速构建出高效、可扩展的企业应用。通过理解并掌握这种集成方式,可以极大地提升开发效率和应用质量。
它们的集成方式有很多种,一种常见的做法是通过Spring来管理Struts的Action实例,同时Spring作为Hibernate的事务管理器,控制数据访问的事务。这样,所有的业务逻辑、数据访问和控制流程都由这三个框架共同完成,...
3. **配置Spring**:创建spring.xml,定义bean的实例化、依赖注入以及事务管理。 4. **配置Hibernate**:设置hibernate.cfg.xml,定义数据源、实体类映射和会话工厂。 5. **编写Action和Service**:Action处理HTTP...
Struts、Spring 和 Hibernate 是Java Web开发中的三大框架,它们共同构建了一个强大的后端架构,为开发复杂的Web应用程序提供了高效且灵活的解决方案。这个BBS系统是基于这三种技术实现的论坛系统,提供了完整的源...
Spring是Java企业级应用开发的全面解决方案,它不仅包含ORM和MVC支持,还提供了依赖注入(DI)、面向切面编程(AOP)、事务管理等核心功能。Spring的IoC容器管理应用的组件,使得组件之间的依赖关系可以外部化,...
Hibernate是一个流行的Java持久层框架,3.3.2版本提供了一个强大的ORM(Object-Relational Mapping)解决方案,使得Java对象可以直接映射到数据库表。它支持JPA(Java Persistence API),提供了缓存机制,以及HQL...
以上是Spring+Hibernate将文件二进制数据持久化到数据库的解决方案,而Struts通过将表单中file类型的组件映射为ActionForm中类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。 工程...
这三者分别是Spring作为应用的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)容器,Hibernate作为ORM(Object-Relational Mapping)解决方案,而WebWork2则是一个轻量级的MVC(Model-View-...
总结来说,"3大框架合并SSH"代表了Java Web开发中的高效能解决方案,它整合了Spring的全面管理、Struts的MVC架构和Hibernate的数据库操作能力,为开发者提供了强大的工具来构建复杂的企业级应用。通过合理配置和优化...
Hibernate支持事务处理、缓存机制以及多种数据库平台,使得数据访问更加便捷和高效。 **Spring框架** Spring是一个全面的企业级应用开发框架,它涵盖了依赖注入(DI)、面向切面编程(AOP)、数据访问、Web应用、...
9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 ...
Spring提供了一套全面的事务管理解决方案,无论是编程式还是声明式的事务管理,都能轻松应对。这使得开发者能够专注于业务逻辑,而不是事务边界的问题。 7. **Spring AOP vs AspectJ** Spring AOP是内建在Spring...
7. **解决方案**:为了解决jar文件管理问题,开发者可以使用构建工具,如Maven或Gradle,它们能自动管理和下载依赖,生成项目的类路径,避免手动合并jar。此外,使用IDE如Eclipse或IntelliJ IDEA,它们通常有内置的...
Spring是Java企业级应用开发中的核心框架,它提供了全面的解决方案,包括依赖注入(Dependency Injection, DI)、面向切面编程(Aspect-Oriented Programming, AOP)、事务管理、数据访问/集成等。DI允许开发者在...
6. **服务化架构**:在大型购物商城系统中,微服务架构可能被采用,Spring Cloud提供了全套的微服务解决方案,包括服务注册、发现、负载均衡等。虽然题目未明确提及,但理解如何将商城系统拆分为多个独立的服务,...