Spring's abstract DAO system is compatible with a variety of data access technologies, each with its own unique features.
Hibernate is a very good ORM implementation, but it's not easy to control the underlying SQL
MyBatis makes it easy to control SQL with templating technology, but without the high development efficiency of Hibernate
The highest degree of freedom is of course the direct use of Spring JDBC, but it is also the lowest, flexible cost 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. So in one application, there are often multiple data access techniques: Generally two, one using ORM technology framework, and the other using partial JDBC as the underlying technology.
Problem
When we adopt: ORM technology Framework + the underlying technology of the partial JDBC how to deal with the problem of transaction management? 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 work together and how?
Solution Solutions
Spring Transaction Management provides a solution for us.
When we adopt a high-end ORM technology (HIBERNATE,JPA,JDO) and adopt a JDBC technology (Spring Jdbc,mybatis), the former session is the encapsulation of the latter connection (Connection), Spring will "be smart enough" to let the former's session encapsulate the latter's connection in the same transactional thread. So, we just have to use the former transaction manager directly.
We enumerate the transaction managers that correspond to the hybrid data access technology:
Example: Hibernate + Spring JDBC
Since it is not generally possible to use 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.
Hibernate + Spring JDBC is probably the most used combination, and we use instances to see how things work.
User uses an entity class for annotation declarations
Import javax.persistence.Entity;Import javax.persistence.Table;Import Javax.persistence.Column;Import Javax.persistence.Id;Import java.io.Serializable; @Entity @Table (Name=public class user implements serializable{ @Id @Column (name = " user_name ") private String userName; private String password; private int score; @Column (name = "Last_logon_time") private long lastlogontime = 0;}
UserService using Hibernate data access technology
Import org.springframework.beans.factory.annotation.Autowired;Import Org.springframework.jdbc.core.JdbcTemplate;Import Org.springframework.context.ApplicationContext;Import Org.springframework.context.support.ClassPathXmlApplicationContext;Import Org.springframework.stereotype.Service;Import Org.springframework.orm.hibernate3.HibernateTemplate;Import Org.apache.commons.dbcp.BasicDataSource;Import user. User;@Service ("UserService")PublicClassUserServiceExtendsBaseservice {@AutowiredPrivate Hibernatetemplate hibernatetemplate; @Autowired private scoreservice scoreservice; public void logon (String userName) { System.out.println ( "logon method ..."); Updatelastlogontime (UserName); //① uses hibernate data access technology Scoreservice.addscore (userName, 20); Span class= "hljs-comment" >//② using spring JDBC data access technology} public void updatelastlogontime (String userName) {System.out.println (//③ see below for Analysis}}
At ①, the data is manipulated using Hibernate, and Scoreservice#addscore () is invoked at ②, which uses Spring JDBC to manipulate the data internally.
At ③, we explicitly call the Flush () method, which synchronizes the cache in the Session to the database, which immediately sends an updated record of the SQL statement to the database .
The flush () method is explicitly executed here because, by default, Hibernate synchronizes the data changes to the database when the transaction commits, and the transaction commits occur before the logon () method returns.
This mechanism of data synchronization latency does not cause any problems if all changes to the database use Hibernate. However, we used both Hibernate and Spring JDBC hybrid data access techniques in the logon () method.
Spring JDBC does not automatically perceive Hibernate first-level caching, so if the flush () method is not called in time to synchronize data changes to the database, the results of data changes through Spring JDBC at ② will be overwritten by changes in the hibernate cache, and the Wuhan test Tube Babies because the first-level cache synchronizes to the database before the logon () method returns!
Scoreservice: Using Spring JDBC data access Technology
Import org.springframework.beans.factory.annotation.Autowired;Import Org.springframework.jdbc.core.JdbcTemplate;Import Org.springframework.stereotype.Service;Import Org.apache.commons.dbcp.BasicDataSource;@Service ("Scoreuserservice")public class scoreservice extends BaseService{ Span class= "hljs-annotation" > @Autowired private jdbctemplate jdbctemplate; public void addscore (String userName, int toadd) {System.out.println ( "UPDATE t_user u SET u.score = U.score +?" WHERE user_name =? "; Jdbctemplate.update (SQL, Toadd, userName); //① see the number of connections that the database has activated basicdatasource Basicdatasource = (basicdatasource) Jdbctemplate.getdatasource (); System.out.println ( "number of active connections:" +basicdatasource.getnumactive ());}}
Key configuration Files
<!--use Hibernate transaction Manager--<BeanId="Hibermanager"class="Org.springframework.orm.hibernate3.HibernateTransactionManager"p:sessionfactory-ref="Sessionfactory"/><!--enforces transactional enhancements to all common methods that inherit the Baseservice class-<Aop:configproxy-target-class="True" ><Aop:pointcutId="Servicejdbcmethod"expression="Within (com.artisan.baseservice+)"/><aop:advisor pointcut-ref= " Servicejdbcmethod "advice-ref=" HiberAdvice "/> </aop:config> < tx:advice id= "HiberAdvice" transaction-manager= "Hibermanager" > <tx:attributes> <tx:method Span class= "Hljs-attribute" >name= "*"/> </ tx:attributes> </tx:advice>
Log:
21st:37:57,062 (Abstractplatformtransactionmanager. Java:365)-Creating new transaction with name [Com. Artisan. UserService. Logon]: Propagation_required,isolation_default21st:37:57,093 (Sessionimpl. Java:)-Opened session at timestamp:1266640737021st:37:57,093 (Hibernatetransactionmanager. Java:493)-Opened new Session [org. Hibernate. impl. Sessionimpl@83020] for Hibernate Transaction①21st:37:57,093 (Hibernatetransactionmanager. Java:504)-Preparing JDBC Connection of Hibernate Session [org. Hibernate. impl. Sessionimpl@83020]21st:37:57,109 (jdbctransaction. Java:-Begin...logon Method...updatelastlogontime ...21st:37:57,109 (Abstractbatcher. Java:401)-Select user0_. User_name as user1_0_0_, user0_. Last_logon_time as last2_0_0_, user0_. password as password0_0_, user0_. Score as score0_0_ from T_user user0_ where user0_. User_name=?Hibernate:select user0_. User_name as user1_0_0_, user0_. Last_logon_time as last2_0_0_, user0_. password as password0_0_, user0_. Score as score0_0_ from T_user user0_ where user0_. User_name=?...21st:37:57,187 (Hibernatetemplate. Java:422)-Not closing Pre-bound Hibernate Session after hibernatetemplate21st:37:57,187 (Hibernatetemplate. Java:397)-Found thread-bound Session for HibernatetemplateHibernate:update T_userSet last_logon_time=?, password=?, score=? where User_name=?...2017-09-2621st:37:57,203 DEBUG [main] (Abstractplatformtransactionmanager. Java:470)-ParticipatingIn existing Transaction②addscore ...2017-09-2621st:37:57,203 DEBUG [main] (JdbcTemplate. Java:785)-Executing prepared SQL update2017-09-2621st:37:57,203 DEBUG [main] (JdbcTemplate. Java:569)-Executing prepared SQL statement [UPDATE t_user uSET u. score = U. score +? WHERE user_name =?]2017-09-2621st:37:57,203 DEBUG [main] (JdbcTemplate. Java:794)-SQL update affected1 Rows Activation Connection number:1③2017-09-2621st:37:57,203 DEBUG [main] (Abstractplatformtransactionmanager. Java:752)-Initiating transaction commit2017-09-26 21:37:57, 203 DEBUG [main] (Hibernatetransactionmanager.java:< Span class= "Hljs-number" >652)-committing Hibernate transaction on Session [Org.impl@83020]④2017-09-< Span class= "Hljs-number" >26 21:37: 57,203 DEBUG [main] (Jdbctransaction.java:103)-Commit⑤
Open a new transaction at ① Userservice#logon (),
At ②, the Scoreservice#addscore () method is added to the transaction context opened at ①.
The output at the ③ is the output from the Scoreservice#addscore () method, reporting that the number of connections activated by the data source is 1, which clearly tells us that Hibernate and JDBC are two data access technologies that "share" a connection in the same transaction context.
At ④, submit a Hibernate transaction,
The underlying Connection commit transaction is then triggered at the ⑤.
After using the Hibernate transaction manager, Hibernate and Spring JDBC data access technologies can be mixed, and they will work in the same transaction context. However, when accessing data using Spring JDBC, Hibernate does not synchronize one or two levels of cache, and the first-level cache latency Data synchronization mechanism may overwrite the results of the Spring JDBC data changes.
Because of the synchronization of transactions in the scenario of mixed data access technology and the cache is out of sync, it is best to use Hibernate to complete the read and write operations, and to do the reading with Spring JDBC . For example, use Spring JDBC for a brief list of queries, and Hibernate to maintain the queried data.
If you do use Hibernate and Spring JDBC to read and write data at the same time, you must take into account the problems raised by the Hibernate caching mechanism: You must fully analyze the data maintenance logic and, if necessary, call Hibernate's Flush () method to avoid overwriting the SPR ing jdbc changes, maintaining Hibernate cache when Spring JDBC changes the database.
The above conclusions can be extended to other hybrid data access technologies, such as hibernate+mybatis,jpa+spring jdbc,jdo+spring JDBC, etc.
Transaction management for Spring jdbc-hybrid framework