The company's project is nearing the end, summarizing the technology used in the project, I found some things in the project is still quite vague, just know how to use it. It's not clear how it works. Because the company's project is older, is a project 7 years ago, the middle has been someone in the maintenance, but also in the process of constant integration of new things, such as the project of the persistence of this piece, the use of ibatis,mybatis, Hibernate,spring JDBC four hybrid framework. The reason can only be said to be a legacy of history, do not do too much explanation. But how so many persistent frameworks work together, especially the control of transactions, the use of so many persistence frameworks in a system is how they properly control their transactions, and even some business logic invokes methods that use these different frameworks. It does sound a little difficult. Do we know that Spring provides the appropriate transaction manager for each data access technology, and does it need to configure the corresponding transaction manager separately for each of them? How do they collaborate and work? These emerging issues often suppress the idea of developers using the joint service.
Response of Spring transaction manager
Spring's abstract DAO system is compatible with a variety of data access technologies, each with its own unique features. Like Hibernate is a very good ORM implementation, but the control of the underlying SQL is not very convenient, while ibatis through templating technology allows you to easily control SQL, but not hibernate as high development efficiency, the highest degree of freedom is the direct use of SPRINGJDBC , but it's also the bottom line, and the cost of flexibility is the complexity of the code. It is hard to say which data access technology is the best, and only in a particular scenario can the answer be given. Therefore, in an application, often use multiple data access technology: Generally two, one using ORM technology framework, and the other using the partial JDBC technology, the two are perfect together to form a joint military, common resist.
in fact, on this issue, we underestimated spring transaction management capabilities.
If you adopt a high-end orm Technology (hibernatejpajdo Technology (spring jdbc ibatis because the former session (sessionspring will be "smart enough" in the same transaction thread to let the former's session encapsulate the latter's connection.
So, we just have to use the former transaction manager directly.
Table 1
Ordinal |
Hybrid data access Technology framework |
Transaction manager |
1 |
hibernate+ Spring jdbc or ibatis |
Org.springframework.orm.hibernate3.HibernateTransactionManager |
2 |
jpa+spring JDBC or Ibatis |
Org.springframework.orm.jpa.JpaTransactionManager |
3 |
jdo+spring JDBC or Ibatis |
Org.springframework.orm.jdo.JdoTransactionManager |
Transaction management for hibernate+spring JDBC Hybrid framework
Since there is generally no case of using multiple ORM frameworks at the same time (such as HIBERNATE+JPA), we do not intend to discuss this proposition, but focus on the ORM Framework +JDBC framework of the case. hibernate+spring JDBC may be the most used combination, and in this section we observe the operation of transaction management through an example.
PackageCom.baobaotao.mixdao; @Service ("UserService") Public classUserServiceextendsBaseservice {@AutowiredPrivatehibernatetemplate hibernatetemplate; @AutowiredPrivateScoreservice Scoreservice; Public voidlogon (String userName) {//① accessing data through Hibernate technologySystem.out.println ("Before Updatelastlogontime () ..."); Updatelastlogontime (UserName); System.out.println ("End Updatelastlogontime ():"); //② accessing data through JDBC technologySystem.out.println ("Before Scoreservice.addscore () ..."); Scoreservice.addscore (UserName,20); System.out.println ("End Scoreservice.addscore ():"); } Public voidupdatelastlogontime (String userName) {User User= Hibernatetemplate.get (User.class, UserName); User.setlastlogontime (System.currenttimemillis ()); Hibernatetemplate.update (user); //③ This sentence is very important, please see the analysis belowHibernatetemplate.flush (); }}
at ①, the data is manipulated using Hibernate, and Scoreservice#addscore () is invoked at ② , whichuses Spring JDBC to manipulate the data internally.
At ③, we explicitly call theFlush ()Method that willSessionTo the database (that is, sending an updated record to the database immediatelySqlstatement). The reason to explicitly executeFlush ()method, because by default, theHibernateChanges to the data are recorded only in the first-level cache, until the transaction commits or explicitly callsFlush () The data in the first-level cache is synchronized to the database, and the operation committing the transaction occurs in logon () method before returning. If all change operations against the database use hibernatelogon () spring jdbc Hybrid data access technology, spring jdbc cannot automatically perceive Span lang= "en-US" >hibernate first-level cache, so if you do not call flush () spring jdbc The changes in the first-level cache are overwritten because hibernate first-level cache waits until logon () The method is not synchronized to the database until it is returned!
scoreservice uses springjdbc data access technology, and its code is as follows:
PackageCom.baobaotao.mixdao;Importorg.springframework.beans.factory.annotation.Autowired;Importorg.springframework.jdbc.core.JdbcTemplate;ImportOrg.springframework.stereotype.Service;ImportOrg.apache.commons.dbcp.BasicDataSource; @Service ("Scoreservice") Public classScoreserviceextendsbaseservice{@AutowiredPrivateJdbcTemplate JdbcTemplate; Public voidAddscore (String UserName,inttoadd) {String SQL= "UPDATE t_user u SET u.score = U.score +?" WHERE user_name =? "; Jdbctemplate.update (SQL, Toadd, userName); Basicdatasource Basicdatasource=(Basicdatasource) Jdbctemplate.getdatasource (); //① See how many connections the database has activated hereSystem.out.println ("[Scoreuserservice.addscore] Activation connection number:" +basicdatasource.getnumactive ()); }}
Spring 's key configuration file code is as follows:
... ..<!--① using Hibernate transaction Manager--<bean id= "Hibermanager"class= "Org.springframework.orm.hibernate3.HibernateTransactionManager"p:sessionfactory-ref= "Sessionfactory"/> <!--② The common methods of UserService and Scoreservice have transactions--<aop:config proxy-target-class= "true" > <aop:pointcut id= "Servicejdbcmethod"expression= "Within (com.baobaotao.mixdao.baseservice+)"/> <aop:advisor pointcut-ref= "Servicejdbcmethod"Advice-ref= "Hiberadvice"/> </aop:config> <tx:advice id= "Hiberadvice" transaction-manager= "Hibermanager" > <tx:attributes> <tx:method name= "*"/> </tx:attributes> </tx:advice> & Lt;/beans>
Start the spring container and execute the Userservice#logon () method to see the following execution log:
before Userservice.logon (): ① after executing Userservice.logon (), Spring opens a transaction Creating New transaction with name [Com.baobaotao.mixdao.UserService.logon]: Propagation_required,isolation_ DEFAULT opened session at timestamp:13009379637openedNewSession [[email protected]] forHibernate Transaction ... Exposing Hibernate transaction as JDBC transaction [Jdbc:mysql://localhost:3306/sampledb, [email protected], Mysql-ab JDBC Driver]before Userservice.updatelastlogontime (): ②userservice.updatelastlogontime () is automatically bound to the session opened at ① when executed Found Thread-bound Session forhibernatetemplate Loading entity: [Com.baobaotao.user#tom] About to open preparedstatement (open preparedstatements : 0, globally:0). About to close PreparedStatement (open preparedstatements:1, Globally:1) not closing pre-bound Hibernate Session after hibernatetemplate end Updatelastlogontime (): Before Scoreservice.addscore (): ③scoreservice.addscore () executes when bound to a session opened at ① and joins the corresponding transaction Found thread-bound Session [[email protected]] forHibernate Transaction participating in existing transaction ... SQL Update affected1Rows④ The data source only opens a connection [Scoreuserservice.addscore] activation connection number:1End Scoreservice.addscore (): initiating transaction commit ⑤ commits the hibernate transaction, it triggers a cache-to-database synchronization committing Hibernate transaction on Session [[ Email protected]] Commit processing flush-Time cascades Dirty checking collections flushed:0 insertions, 0 updates, 0 deletions to 1Objects Flushed:0 (re) creations, 0 updates, 0 removals to 0Collections Listing Entities:com.baobaotao.user{lastlogontime=1300937963882, score=10, Username=tom, password=123456} re-enabling Autocommit⑥ the corresponding transaction of the JDBC Connection bounded by the underlying session committed JDBC Connection transaction completed On session with On_close connection release mode; Be sure to close the session to release JDBC resources!Closing Hibernate session [[email protected]] After transaction Closing Hibernate session releasing JDBC connection [ (Open preparedstatements:0, globally:0) (Open resultsets:0, globally:0)] Transaction completed on session with On_close connection release mode; Be sure to close the session to release JDBC resources!After Userservice.logon () :
watch this output log carefully, at ① userservice#logon () userservice#updatelastlogontime () scoreservice#addscore () scoreservice#addscore () hibernate and jdbc hibernate transaction, and then trigger the call to the underlying ⑥ connection commit the transaction.
from the results of the above operation, we can draw the conclusion that: using hibernate After the transaction manager, you can mix hibernatespringjdbc data access technology, which works in the same transaction context. But using springjdbc when accessing data, hibernate Level one or two cache is not synchronized, in addition, the first-level cache latency Data synchronization mechanism may overwrite the results of springjdbc data changes.
due to the existence of "transactional synchronization and cache out-of-sync" in mixed data access technology scenarios, So it is best to use hibernatespringjdbc For read operations. such as with spring jdbc for a brief list of queries, and hibernate Maintenance of the data being queried.
If you really want to use spring jdbc Read and write data, you must take full account of Hibernate The caching mechanism raises the problem that the data maintenance logic must be analyzed in a holistic manner, and call hibernateflush () spring jdbcspring jdbc when changing the database, maintain the cache of hibernatespring jdbchibernate
The above conclusions can be extended to other hybrid data access technologies, such as Hibernate+ibatis,jpa+springjdbc, jdo+spring JDBC, and so on.
http://blog.csdn.net/hy6688_/article/details/44783865
Spring Transaction Management--analysis of the situation when multiple ORM frameworks are in use