|
|||||||||||
PREV NEXT | FRAMES NO FRAMES |
The main purpose of this jdto Framework is to have some generic classes, which are reusable to any project where plain DAO's are used.
See:
Description
Packages | |
com.framework.jdto.exceptions | |
com.framework.jdto.finder | |
com.framework.jdto.jdbc.wrapper | |
com.framework.jdto.properties | |
com.framework.jdto.transaction |
The main purpose of this jdto Framework is to have some generic classes, which are reusable to any project where plain DAO's are used.
Purpose
In general, developers forget to close or release the database connections while writing DAO's, which leads to problems. The main purpose of this Framework is to have some generic classes where...
The user or developer shouldn't worry about getting or releasing the Database Connections in each and every method of the DAO's that are written for any project.
Providing an optional Transaction Support for DAO's written by the developer.
Overview
The framework contains wrapper classes for java.sql.PreparedStatement and java.sql.Statement. These Wrapper classes are PreparedStatementWrapper and StatementWrapper. These classes should be used by the developer for writing the DAO's. These Wrapper Classes takes care of getting and releasing/closing the Database Connections.
1. Setting up the DataSource
One most important aspect of this framework is setting up the datasource. The framework uses the ServiceFinder Class to locate the datasource. This class Follows the ServiceLocator Design Pattern, which is basically a SingleTon Class. it Locates the DataSource provided, its DataSourceJNDIName, InitialContextFactory and ProviderURL is set in jdto.properties. User needs to create a jdto.properties file and make the properties file available in the classpath for framework to use. Once these values are set, all the DAO's and the TransactionContextManager takes care of locating the DataSource.
Sample jdto.properties
DataSourceJNDIName = mydatasource
InitialContextFactory = weblogic.jndi.T3InitialContextFactory //for weblogic server
ProviderURL = t3://localhost:7001 //for weblogic server
2. Using PreparedStatementWrapper and StatementWrapper Classes in your DAO's
Database Insert Query - executeUpdate():
public int saveAddress(AddressVO address) {
int result1=0;
String sql = "insert into ADDRESS(ADDRESS_ID, NAME, STREET, CITY, PROVINCE)values(?,?,?,?,?)";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql);
stmt.setString(1, address.getAddressID());
stmt.setString(2, address.getName());
stmt.setString(3, address.getStreet());
stmt.setString(4, address.getCity());
stmt.setString(5, address.getProvince());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in saveAddress::AddressDAO", daoe);
}
return result1;
}
Database Update Query - executeUpdate():
public int updateAddress(AddressVO address) {
int result1=0;
String sql = "UPDATE ADDRESS SET NAME=?, STREET=?,CITY=?,PROVINCE=? WHERE ADDRESS_ID=?";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql);
stmt.setString(1, address.getName());
stmt.setString(2, address.getStreet());
stmt.setString(3, address.getCity());
stmt.setString(4, address.getProvince());
stmt.setString(5, address.getAddressID());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in updateAddress of AddressDAO", daoe);
}
return result1;
}Database Delete Query - execute():
public boolean deleteAddress(AddressVO address) {
boolean result=false;
String sql = "DELETE FROM ADDRESS WHERE ADDRESS_ID=?";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql);
stmt.setString(1, address.getAddressID());
result = stmt.execute();
} catch (DAOException daoe) {
_log.error("Exception in updateAddress of AddressDAO", daoe);
}
return result;
}Database Select Query - executeQuery(RowMapper rm):
This is a different case as the executeQuery method takes RowMapper object as an argument and returns an java.lang.Object type of Object. So all your DAO should implement RowMapper interface in order to call the executeQuery() method of PreparedStatementWrapper or StatementWrapper classes and override the mapRow(ResultSet addressRsltSet) method of the RowMapper interface.
See the getAddress() method of AddressDAO.java provided as a sample in this package. The getAddress() method calls executeQuery(this); on the PreparedStatementWrapper Object in AddressDAO class. The executeQuery(RowMapper) method of PreparedStatementWrapper Object in turn calls the mapRow(ResultSet addressRsltSet) of the AddressDAO class by passing the java.sql.ResultSet Object. The mapRow(ResultSet addressRsltSet) of AddressDAO maps the ResultSet to the required Object and returns an java.lang.Object type of Object, which should be type casted in the calling method (i.e.,getAddress()).
if there is a need for more than one select queries in your DAO then see the getAddressByID(AddressVO address) method of AddressDAO class, which uses a new class called AddressByID implements RowMapper to pass as an argument to executeQuery() method of PreparedStatementWrapper Class.
AddressVO address = (AddressVO) addressPrepStmt.executeQuery(new AddressByID());
The class AddressByID is written in the same AddressDAO.java
class AddressByID implements RowMapper {
public Object mapRow(ResultSet addressRsltSet) throws SQLException {
AddressVO addressVO = new AddressVO();
while (addressRsltSet.next()) {
addressVO.setAddressID(addressRsltSet.getString("ADDRESS_ID"));
addressVO.setName(addressRsltSet.getString("NAME"));
addressVO.setStreet(addressRsltSet.getString("STREET"));
addressVO.setCity(addressRsltSet.getString("CITY"));
addressVO.setProvince(addressRsltSet.getString("PROVINCE"));
}
return addressVO;
}
}
Similarly you can use the StatementWrapper class....
3. Using Transactions with your DAO's
TransactionContextManager class is mainly responsible for managing the transactions. it is responsible for beginning the transaction and ending the transaction based on the current transaction status. User needs to call the beginTransaction() method to begin the transaction and should end the transaction by calling the endTransaction() method. All the DAO's which are executed after the beginTransaction() method and before the endTransaction() method by default runs in a transaction, provided the DAO's use the PreparedStatementWrapper or StatementWrapper classes to interact with the database (i.e., Insert, Update, Delete and Select Queries) instead of the actual java.sql.PreparedStatement and java.sql.Statement class.
Currently TransactionContextManager doesn't support Nested Transactions. it throws a NotSupportedException if the user tries to get a Nested Transaction.
TransactionContextManager class ends the transaction by calling commit or rollback, when the user calls the endTransaction() method based on the current Transaction Status.
Each PreparedStatementWrapper or StatementWrapper objects will have their own transaction status, which will be either TransactionStatus.STATUS_MARKED_ROLLBACK or TransactionStatus.STATUS_MARKED_COMMIT based on the success or failure of the query. TransactionContextManager is responsible for collecting the statuses of all the PreparedStatementWrapper or StatementWrapper objects that are executed between beginTransaction() and endTransaction() methods and completes the transaction by calling commit or rollback based on the final Transaction Status.
If the transaction status of all the PreparedStatementWrapper or StatementWrapper objects are STATUS_MARKED_COMMIT then the TransactionContextManager commits the Transaction. But if at least one transaction status of PreparedStatementWrapper or StatementWrapper object is STATUS_MARKED_ROLLBACK then TransactionContextManager rollbacks the Transaction.
PreparedStatementWrapper and StatementWrapper objects throws DAOException whenever an SQL Query Fails or a database error occurs. If this happens the TransactionContextManager rollback's the Transaction.
There are 2 ways of starting a Transaction.
If the user starts the transaction by calling the first one (TransactionContextManager.beginTransaction()), then all the DAO's which are executed after that will by default runs in a Transaction.
But if the user starts the transaction by calling the second one, then its the users responsibility to call the second one (setSql(..., true) method) for each and every PreparedStatementWrapper or StatementWrapper object, which needs to run in the same Transaction. In this case if the user wants to end the transaction then JDBCTemplate.finishTransaction() method has to be called.
In Both the above cases user can call the TransactionContextManager.endTransaction() to end the transaction.
Case-2 will be useful whenever the developer wants some dao's to run in a Transaction and some not in a Transaction, in a bunch of DAO's. see the example below.
How To Use This Framework
Case - I : By calling TransactionContextManager.beginTransaction() method
Example using TransactionContextManager's beginTransaction() and endTransaction().
TransactionContextManager.beginTransaction();
//DAO - 1
MemberDAO memberDAO = new MemberDAO();
memberDAO.saveMember(new MemberVO("1","Cindy","Lake Hill","Halifax","5R6T8O"));
//DAO - 2
AddressDAO addressDAO = new AddressDAO();
addressDAO.saveAddress(new AddressVO("1","Cindy","Lake Hill","Halifax","5R6T8O"));
//DAO - 3
//create some LoanDAO and save/update the Details of LoanDAO
//LoanDAO.saveLoanDetails(MemberVO);
//....... DAO - 4 .... and so on...
TransactionContextManager.endTransaction();saveMember(MemberVO member) Method
public int saveMember(MemberVO member) {
int result1=0;
String sql = "insert into ADDRESS(ADDRESS_ID, NAME, STREET, CITY, PROVINCE)values(?,?,?,?,?)";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql);
stmt.setString(1, member.getMemberID());
stmt.setString(2, member.getName());
stmt.setString(3, member.getStreet());
stmt.setString(4, member.getCity());
stmt.setString(5, member.getProvince());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in saveMember::MemberDAO", daoe);
}
return result1;
}saveAddress(MemberVO member) Method
public int saveAddress(AddressVO address) {
int result1=0;
String sql = "insert into ADDRESS(ADDRESS_ID, NAME, STREET, CITY, PROVINCE)values(?,?,?,?,?)";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql);
stmt.setString(1, address.getAddressID());
stmt.setString(2, address.getName());
stmt.setString(3, address.getStreet());
stmt.setString(4, address.getCity());
stmt.setString(5, address.getProvince());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in saveAddress::AddressDAO", daoe);
}
return result1;
}
Case - II : By calling PreparedStatementWrapper or StatementWrapper object's setSql
//DAO - 1- This DAO should run in Transaction. This DAO Starts the Transaction, Since this is the first one to run in a Transaction.
MemberDAO1 memberDAO1 = new MemberDAO1();
memberDAO1.saveMember(new MemberVO("1","Cindy","Lake Hill","Halifax","5R6T8O"));
//DAO - 2 - This DAO should NEVER run in Transaction.
AddressDAO addressDAO = new AddressDAO();
addressDAO.saveAddress(new AddressVO("1","Cindy","Lake Hill","Halifax","5R6T8O"));
//DAO - 3 - This DAO should run in Transaction
//create some LoanDAO and save/update the Details of LoanDAO
LoanDAO.saveLoanDetails(MemberVO);
//....... DAO - 5 .... and so on...
//DAO - n
//This DAO run in Transaction
AddressDAO1 addressDAO1 = new AddressDAO1();
addressDAO1.saveAddress(new AddressVO("1","Cindy","Lake Hill","Halifax","5R6T8O"));
//Now you need to End the Transaction. Here it can be done in 2 ways. You can Call the finishTransaction() method of the JDBCTemplate
//or the endTransaction() method of TransactionContextManager.JDBCTemplate.finishTransaction();
//OR
TransactionContextManager.endTransaction();saveMember(MemberVO member) Method
public int saveMember(MemberVO member) {
int result1=0;
String sql = "insert into ADDRESS(ADDRESS_ID, NAME, STREET, CITY, PROVINCE)values(?,?,?,?,?)";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql, true);//This statement runs the current SQL Query in a Transaction.
stmt.setString(1, member.getMemberID());
stmt.setString(2, member.getName());
stmt.setString(3, member.getStreet());
stmt.setString(4, member.getCity());
stmt.setString(5, member.getProvince());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in saveMember::MemberDAO", daoe);
}
return result1;
}saveAddress(MemberVO member) Method
public int saveAddress(AddressVO address) {
int result1=0;
String sql = "insert into ADDRESS(ADDRESS_ID, NAME, STREET, CITY, PROVINCE)values(?,?,?,?,?)";
PreparedStatementWrapper stmt = new PreparedStatementWrapper();
try {
stmt.setSql(sql, true);//This statement runs the current SQL Query in a Transaction.
stmt.setString(1, address.getAddressID());
stmt.setString(2, address.getName());
stmt.setString(3, address.getStreet());
stmt.setString(4, address.getCity());
stmt.setString(5, address.getProvince());
result1 = stmt.executeUpdate();
} catch (DAOException daoe) {
_log.error("Exception in saveAddress::AddressDAO", daoe);
}
return result1;
}
Note: If this framework is used for J2EE 1.3 and above for IBM Websphere the DataSource must be configured as an UnSharable Resource.
=================================================================================
|
|||||||||||
PREV NEXT | FRAMES NO FRAMES |