/**
Author: willpower
Source: rifoo Technology (http://www.rifoo.com)
Time: 2006-01 1
Remarks: Reprinted please keep the above statement
**/
After the previous section discusses simple transaction processing, this section mainly discusses Transaction Processing on multiple databases.
If we want to refactor a simple application to make it use multiple resources, spring's pluggable transaction policy (Pluggable Transaction Strategies) can help us save development time. In this example, we will use a JTA transaction to extend it to multiple database sources. To make the example application work normally, it needs to run in a J2EE container that recognizes JTA.
If we are using agile development to develop programs, we are likely to experience such a scenario. Agile approach suggestion: simplify the problem and implement more complex features only when necessary. Dependency injection allows us to easily change application resources and easily insert them into another specified application.
In this example, we will maintain the cash Service (monetary transaction) in a separate database named mongoabikeaccounts ). Whenever a user makes a reservation, they will provide a deposit in advance, and we will add the number of deposits to the monetarytransactions table of the new database in the form of transactions.
The database creation and table creation scripts are as follows:
Example 7-5. rentabike. SQL
Create Database Export abikeaccounts;
Use your abikeaccounts;
Create Table monetarytransactions (
Txid int (11) not null auto_increment,
Resid int (11) not null default '0 ',
Amount double not null default '0 ',
'Type' varchar (50) not null,
Primary Key (txid ))
Type = InnoDB;
Do not forget to create an authorized user account for the new database in MySQL:
Grant all privileges on your abikeaccounts. * to 'Your abikeaccounts' @ 'localhost'
With grant option;
We created a user named mongoabikeaccounts who has full permissions on the new database.
Next, we create a persistent domain class:
Example 7-6. monetarytransaction. Java
Public class monetarytransaction {
Private int txid;
Private int resid;
Private double amount;
Public int gettxid (){
Return txid;
}
Public void settxid (INT txid ){
This. txid = txid;
}
Public int getresid (){
Return custid;
}
Public void setresid (INT resid ){
This. resid = resid;
}
Public double getamount (){
Return amount;
}
Public void setamount (double amount ){
This. Amount = amount;
}
Public monetarytransaction (double amount, int resid ){
This. resid = resid;
This. Amount = amount;
This. txid =-1;
}
Public monetarytransaction (){
This (0.0, 0 );
}
}
Map this class to the database schema:
Example 7-7. monetarytransaction. HBM. xml
<Hibernate-mapping>
<Class name = "com. Springbook. monetarytransaction"
Table = "monetarytransactions">
<ID name = "txid" column = "txid" type = "Java. Lang. Integer"
Unsaved-value = "-1">
<Generator class = "native"> </generator>
</ID>
<Property name = "resid" column = "resid" type = "int"/>
<Property name = "amount" column = "amount" type = "double"/>
</Class>
</Hibernate-mapping>
To access this new database, we must configure another data source and sessionfactory. A sessionfactory is used to process access to a database. Therefore, we need to create a new sessionfactory for this new database.
Example 7-8. RentABikeApp-Servlet.xml
<Bean id = "performanceforaccounts"
Class = "org. springframework. JDBC. datasource. drivermanagerdatasource">
<Property name = "driverclassname">
<Value> com. MySQL. JDBC. Driver </value>
</Property>
<Property name = "url">
<Value> JDBC: mysql: // localhost/justbikes </value>
</Property>
<Property name = "username"> <value> deleabikeaccounts </value> </property>
</Bean>
<Bean id = "sessionfactoryforaccounts"
Class = "org. springframework. Orm. hibernate. localsessionfactorybean">
<Property name = "datasource"> <ref local = "performanceforbikes"/> </property>
<Property name = "mappingresources">
<List>
<Value> COM/Springbook/monetarytransaction. HBM. xml </value>
</List>
</Property>
<Property name = "hibernateproperties">
<Props>
<Prop key = "hibernate. dialect">
Net. SF. hibernate. dialect. mysqldialect
</Prop>
<Prop key = "hibernate. show_ SQL"> false </prop>
</Props>
</Property>
</Bean>
However, we cannot directly use this new sessionfactory in the implementation class of the hibateabike interface. This is because hibateabike extends the hibernatedaosupport class provided by spring. This class uses a single sessionfactory as the return of gethibernatetemplate. Therefore, we need another facade class. This new facade class uses this new sessionfactory to access our new database.
Example 7-9. Accounts. Java
Public interface accounts {
Void addtx (monetarytransaction Tx );
Monetarytransaction gettx (int id );
List gettxs ();
}
Example 7-10. abstrabikeaccounts. Java
Public class accountabikeaccounts
Extends hibernatedaosupport
Implements accounts {
Public void addtx (monetarytransaction Tx ){
Gethibernatetemplate (). saveorupdate (TX );
}
Public monetarytransaction gettx (int id ){
Return (monetarytransaction) gethibernatetemplate ().
Load (monetarytransaction. Class, new INTEGER (ID ));
}
Public list gettxs (){
Return gethibernatetemplate (). Find ("from monetarytransaction ");
}
}
Next, we need to configure the facade in the application:
Example 7-11. RentABike-servlet.xml
<Bean id = "rentabikeaccountstarget"
Class = "com. Springbook. javasabikeaccounts">
<Property name = "sessionfactory">
<Ref local = "sessionfactoryforaccounts"/>
</Property>
</Bean>
<Bean id = "rentabikeaccounts"
Class = "org. springframework. AOP. Framework. proxyfactorybean">
<Property name = "proxyinterfaces">
<Value> com. Springbook. Accounts </value>
</Property>
<Property name = "interceptornames">
<Value> transactioninterceptor, rentabikeaccountstarget </value>
</Property>
</Bean>
Finally, to use this new function in rentabike facade, we need to add the setter method to rentabike so that spring dependencies can be injected. The following code is the content to be added to rentabike facade:
Example 7-12. hibateabike. Java
Private accounts accountsfacade;
Public accounts getaccountsfacade (){
Return accountsfacade;
}
Public void setaccountsfacade (Accounts accountsfacade ){
This. accountsfacade = accountsfacade;
}
Public void addreservation (reservation, double amount)
Throws addreservationexception {
Try {
Monetarytransaction Tx = new monetarytransaction (amount,
Reservation. getreservationid ());
Gethibernatetemplate (). saveorupdate (reservation );
Accountsfacade. addtx (TX );
} Catch (exception ex ){
Throw new addreservationexception ();
}
}
Then look at the code to be added in the configuration file:
Example 7-13. App-Servlet.xml
<Bean id = "rentabiketarget" class = "com. Springbook. hibateabike">
<Property name = "storename"> <value> Bruce's bikes </value> </property>
<Property name = "sessionfactory"> <ref local = "sessionfactory"/> </property>
<Property name = "accountsfacade">
<Ref local = "rentabikeaccounts"/>
</Property>
</Bean>
<Bean id = "transactionmanager"
Class = "org. springframework. transaction. JTA. jtatransactionmanager">
</Bean>
<Bean name = "transactioninterceptor"
Class = "org. springframework. transaction. Interceptor. transactioninterceptor">
<Property name = "transactionmanager">
<Ref local = "transactionmanager"/>
</Property>
<Property name = "transactionattributesource">
<Value>
Com. Springbook. rentabike. transferreservation = propagation_required,
-Reservationtransferexception
Com. Springbook. rentabike. addreservation = propagation_required,
-Addreservationexception
</Value>
</Property>
</Bean>
Summary:
After adding the second data source, we can easily add the distributed transaction function to the application. At any time. when the addreservation () method is called, the application adds the reservation information to the original database in a transactional manner, and adds the generated cash business to another new database. We have added some new classes for the domain model, but most of them are obtained through configuration settings. Spring's support for Hibernate and JTA processes most of the important work. Now, applications process multiple physical data storage in a single distributed transaction.
The notes and summary of this series are over. In fact, this book is not highly appraised on Amazon, but it can be used quickly. It is helpful to understand the Spring framework as a whole.