下面就jpetstore的账号管理部分,来分析一下jpetstore的各层之间的关系:
1。持久层分析
1.1账号管理的iBatis的xml影射部分如下:
账号管理涉及到四张表:
signon 存放用户名,密码
account, 存放用户的基本信息
profile, 存放用户选择的语言,以及喜爱的商品分类
bannerdata 目前不清楚
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
《账号信息结果集》
<resultMap id="result" class="org.springframework.samples.jpetstore.domain.Account">
<result property="username" column="userid" columnIndex="1"/>
<result property="email" column="email" columnIndex="2"/>
<result property="firstName" column="firstname" columnIndex="3"/>
<result property="lastName" column="lastname" columnIndex="4"/>
<result property="status" column="status" columnIndex="5"/>
<result property="address1" column="addr1" columnIndex="6"/>
<result property="address2" column="addr2" columnIndex="7"/>
<result property="city" column="city" columnIndex="8"/>
<result property="state" column="state" columnIndex="9"/>
<result property="zip" column="zip" columnIndex="10"/>
<result property="country" column="country" columnIndex="11"/>
<result property="phone" column="phone" columnIndex="12"/>
<result property="languagePreference" column="langpref" columnIndex="13"/>
<result property="favouriteCategoryId" column="favcategory" columnIndex="14"/>
<result property="listOption" column="mylistopt" columnIndex="15"/>
<result property="bannerOption" column="banneropt" columnIndex="16"/>
<result property="bannerName" column="bannername" columnIndex="17"/>
</resultMap>
《根据用户名,获得用户信息》
<select id="getAccountByUsername" resultMap="result">
select
signon.username as userid,
account.email,
account.firstname,
account.lastname,
account.status,
account.addr1,
account.addr2,
account.city,
account.state,
account.zip,
account.country,
account.phone,
profile.langpref,
profile.favcategory,
profile.mylistopt,
profile.banneropt,
bannerdata.bannername
from account, profile, signon, bannerdata
where account.userid = #value#
and signon.username = account.userid
and profile.userid = account.userid
and profile.favcategory = bannerdata.favcategory
</select>
《根据账号,密码,获取账号》
<select id="getAccountByUsernameAndPassword" resultMap="result">
select
signon.username as userid,
account.email,
account.firstname,
account.lastname,
account.status,
account.addr1,
account.addr2,
account.city,
account.state,
account.zip,
account.country,
account.phone,
profile.langpref,
profile.favcategory,
profile.mylistopt,
profile.banneropt,
bannerdata.bannername
from account, profile, signon, bannerdata
where account.userid = #username#
and signon.password = #password#
and signon.username = account.userid
and profile.userid = account.userid
and profile.favcategory = bannerdata.favcategory
</select>
《获取系统用户名列表》
<select id="getUsernameList" resultClass="java.lang.String">
select username as value from signon
</select>
《更新账号信息》
<update id="updateAccount">
update account set email = #email#, firstname = #firstName#, lastname =
#lastName#, status = #status#, addr1 = #address1#, addr2 =
#address2:varchar#, city = #city#, state = #state#, zip = #zip#,
country = #country#, phone = #phone# where userid = #username#
</update>
《增加新账号》
<insert id="insertAccount">
insert into account (email, firstname, lastname, status, addr1, addr2,
city, state, zip, country, phone, userid) values (#email#, #firstName#,
#lastName#, #status#, #address1#, #address2:varchar#, #city#, #state#,
#zip#, #country#, #phone#, #username#)
</insert>
《更新用户profile表,其中包括用户语言选择,以及喜欢的动物分类
<update id="updateProfile">
update profile set langpref = #languagePreference#, favcategory =
#favouriteCategoryId#, mylistopt = #listOptionAsInt#, banneropt =
#bannerOptionAsInt# where userid = #username#
</update>
《增加用户profile信息〉
<insert id="insertProfile">
insert into profile (langpref, favcategory, mylistopt, banneropt,
userid) values (#languagePreference#, #favouriteCategoryId#,
#listOptionAsInt#, #bannerOptionAsInt#, #username#)
</insert>
〈更新用户密码〉
<update id="updateSignon">
update signon set password = #password# where username = #username#
</update>
〈增加用户名,密码到用户登录表Signon〉
<insert id="insertSignon">
insert into signon (password,username) values (#password#,#username#)
</insert>
</sqlMap>
1.2 Account为账号管理的POJO类,AccountDao 为账号管理interface,规定了一系列方法:
public interface AccountDao {
Account getAccount(String username) throws DataAccessException;
Account getAccount(String username, String password) throws DataAccessException;
void insertAccount(Account account) throws DataAccessException;
void updateAccount(Account account) throws DataAccessException;
List getUsernameList() throws DataAccessException;
}
1.3Account interface 实现:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
public Account getAccount(String username) throws DataAccessException {
return (Account) getSqlMapClientTemplate().queryForObject("getAccountByUsername", username);
}
根据用户名,密码,获得账号
public Account getAccount(String username, String password) throws DataAccessException {
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
return (Account) getSqlMapClientTemplate().queryForObject("getAccountByUsernameAndPassword", account);
}
创建账号,需要更新account,signon,profile三张表
public void insertAccount(Account account) throws DataAccessException {
getSqlMapClientTemplate().insert("insertAccount", account);
getSqlMapClientTemplate().insert("insertProfile", account);
getSqlMapClientTemplate().insert("insertSignon", account);
}
更新账号,需要更新account,signon,profile三张表
public void updateAccount(Account account) throws DataAccessException {
getSqlMapClientTemplate().update("updateAccount", account, 1);
getSqlMapClientTemplate().update("updateProfile", account, 1);
if (account.getPassword() != null && account.getPassword().length() > 0) {
getSqlMapClientTemplate().update("updateSignon", account, 1);
}
}
《获取系统用户名列表》
public List getUsernameList() throws DataAccessException {
return getSqlMapClientTemplate().queryForList("getUsernameList", null);
}
}
总结:
iBatis持久层使用sql-map-config.xml配置所有ibatis .xml文件
<sqlMapConfig>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Account.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Category.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Product.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Item.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Order.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/LineItem.xml"/>
<sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/Sequence.xml"/>
</sqlMapConfig>
使用dataAccessContext-config.xml配置所有DAO实现
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
2,持久层和业务逻辑层的耦合,业务逻辑接口中包含了AccountDAO的接口操作
public interface PetStoreFacade {
Account getAccount(String username);
Account getAccount(String username, String password);
void insertAccount(Account account);
void updateAccount(Account account);
List getUsernameList();
。。。。。。。
}
业务逻辑对象PetStoreImpl 实现了对accountDao的再次封装
public class PetStoreImpl implements PetStoreFacade, OrderService {
private AccountDao accountDao;
public Account getAccount(String username) {
return this.accountDao.getAccount(username);
}
public Account getAccount(String username, String password) {
return this.accountDao.getAccount(username, password);
}
public void insertAccount(Account account) {
this.accountDao.insertAccount(account);
}
public void updateAccount(Account account) {
this.accountDao.updateAccount(account);
}
public List getUsernameList() {
return this.accountDao.getUsernameList();
}
。。。。
}
总结:
持久层与业务逻辑层的耦合是在applicationContext.cml中:
为业务逻辑层提供事务管理
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="petStore" parent="baseTransactionProxy">
<property name="target">
<bean class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
<property name="accountDao" ref="accountDao"/>
<property name="categoryDao" ref="categoryDao"/>
<property name="productDao" ref="productDao"/>
<property name="itemDao" ref="itemDao"/>
<property name="orderDao" ref="orderDao"/>
</bean>
</property>
4表示层和业务逻辑层的耦合:
表示层和业务逻辑层的耦合是通过BaseAction来实现的,并通过接口来访问业务逻辑对象:
public abstract class BaseAction extends Action {
private PetStoreFacade petStore;
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
if (actionServlet != null) {
ServletContext servletContext = actionServlet.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
this.petStore = (PetStoreFacade) wac.getBean("petStore");
}
}
protected PetStoreFacade getPetStore() {
return petStore;
}
}
所有的系统里面的Action都是从BaseAction派生过来的,而BaseAction的派生类中,提供了对业务逻辑对象
PetStoreFacade 的访问。