spring + ibatis jpetstore 摘要
来源:互联网 发布:上海灵娱网络怎么样 编辑:程序博客网 时间:2024/05/12 06:38
spring + ibatis jpetstore 摘要
DB layer涉及的package:
org.springframework.samples.jpetstore.dao 包含dao interface
org.springframework.samples.jpetstore.dao.ibatis 包含dao interface ibatis implement
org.springframework.samples.jpetstore.dao.ibatis.maps (!重要)定义了ibatis pojo与db table的mapping xml file
org.springframework.samples.jpetstore.dao.domain 包含dao ibatis implement使用的pojo
其中比较特别的是org.springframework.samples.jpetstore.dao.ibatis.maps package,里面定义了ibatis pojo与db table的mapping和SQL语句的xml file。以其中的Account为例:
Account pojo:
public class Account implements Serializable {
private String username;
private String password;
private String address1;
....
}
注意:Account pojo不只对应一个table,而是包含了4个table的data: account, profile, signon, bannerdata table.
SqlMapAccountDao (account ibatis dao implement):
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
public Account getAccount(String username, String password) throws DataAccessException {
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
//queryForObject方法第一个参数对应的是ibatis mapping xml的<select>/<insert>/<update>的id属性值,见下面的Account.xml
//第二个参数包含了传给ibatis mapping xml的对应的SQL的参数值
return (Account) getSqlMapClientTemplate().queryForObject("getAccountByUsernameAndPassword", account);
}
....
}
Account.xml (in org.springframework.samples.jpetstore.dao.ibatis.maps folder) 定义了ibatis pojo与db table的mapping和SQL语句
<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="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>
。。。。
<update id="updateSignon">
update signon set password = #password# where username = #username#
</update>
<insert id="insertSignon">
insert into signon (password,username) values (#password#,#username#)
</insert>
</sqlMap>
最后在spring config xml file里的相关定义为:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- Transaction manager for a single JDBC DataSource -->
<!-- (see dataAccessContext-jta.xml for an alternative) -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- SqlMap setup for iBATIS Database Layer -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<!-- sql map config xml-->
<property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- ========================= DAO DEFINITIONS: IBATIS IMPLEMENTATIONS ========================= -->
<bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
WEB-INF/sql-map-config.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>
要特别提及的一个dao是SqlMapSequenceDao,它只有实现类,没有接口,这是因为it is only for ibatis。该dao是用来获取各个table(如order, item)的递增id。在jpetstore里只有order table使用递增id。该dao实现的做法是:
1. 在db方面,table sequence有两个columns,name and nextid。name用来标记对应哪个table,nextid标记当前的递增id的值。例如对于order table,对应的sequence table就有一个record:name='ordernum', nextid的初始化值为1。
2. 在pojo方面,Sequence pojo对应table sequence, mapping xml file is sequence.xml
3. 在orderDao insertOrder时,就会先调用SqlMapSequenceDao的getNextId(name)方法,该方法会返回当前的递增id,并update nextId value + 1
* spring mvc你的FormController对应的form class通常与FormController放在同一个package里。如AccountFormController and AccountForm class
org.springframework.beans.support.PagedListHolder,这是一个有用的类,用来把list可以分页显示。
该class的构造方法以List为参数,如:
PagedListHolder itemList = new PagedListHolder(petStore.getItemListByProduct(productId));
itemList.setPageSize(4); //设置把list分成几个page
如果要显示上一个page/下一个page,使用下列代码:
itemList.previousPage();
itemList.nextPage();
那么要获取current page的list,使用代码:
Class:
itemList.getPageList()
JSP:
<c:forEach var="item" items="${itemList.pageList}">
在对list进行分页显示时,会把PagedListHolder object存在session里,然后不论是查看哪一页,都是先从session里获取PagedListHolder object。详见ViewProductController
add cart item core codes:
//get cart session, if not exist, create a cart session
Cart cart = (Cart) WebUtils.getOrCreateSessionAttribute(request.getSession(), "sessionCart", Cart.class);
//check要add的item是否已经存在,如果已经存在的话,则在原来存在于session cart的该item的数量+1
String workingItemId = request.getParameter("workingItemId");
if (cart.containsItemId(workingItemId)) {
cart.incrementQuantityByItemId(workingItemId);
}
//如果要add的item不存在,就把它add to session cart
else {
// isInStock is a "real-time" property that must be updated
// every time an item is added to the cart, even if other
// item details are cached.
boolean isInStock = this.petStore.isItemInStock(workingItemId);
Item item = this.petStore.getItem(workingItemId);
cart.addItem(item, isInStock);
}
spring WebUtils有2个有用的方法for get session
//get session. 它相当于request.getSession().getAttribute("userSession");
UserSession userSession = (UserSession) WebUtils.getRequiredSessionAttribute(request, "userSession");
//get session. If not exist, create it
Cart cart = (Cart) WebUtils.getOrCreateSessionAttribute(request.getSession(), "sessionCart", Cart.class);
jpetstore并不是所有的page都需要log in之后才能够见到,只有edit account and 与order相关的page才需要log on之后才可以access。因此在access这些page之前要check是否有log in,jpetstore使用的是interceptor方式(见SignonInterceptor),那么下列代码就是在config xml file设置部分page通过interceptor来check是否log in:
<bean id="secureHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="signonInterceptor"/>
</list>
</property>
<property name="urlMap">
<map>
<entry key="/shop/editAccount.do" value-ref="secure_editAccount"/>
<entry key="/shop/listOrders.do" value-ref="secure_listOrders"/>
<entry key="/shop/newOrder.do" value-ref="secure_newOrder"/>
<entry key="/shop/viewOrder.do" value-ref="secure_viewOrder"/>
</map>
</property>
</bean>
<bean id="secure_viewOrder" class="org.springframework.samples.jpetstore.web.spring.ViewOrderController">
<property name="petStore" ref="petStore"/>
</bean>
。。。。。
上述设置表示有4个page在access之前会插入signonInterceptor来check log in。
public class SignonInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
UserSession userSession = (UserSession) WebUtils.getSessionAttribute(request, "userSession");
if (userSession == null) {
//获得在log in之后要forward的link
String url = request.getServletPath();
String query = request.getQueryString();
ModelAndView modelAndView = new ModelAndView("SignonForm");
if (query != null) {
modelAndView.addObject("signonForwardAction", url+"?"+query);
}
else {
modelAndView.addObject("signonForwardAction", url);
}
//关键方法
throw new ModelAndViewDefiningException(modelAndView);
}
else {
return true;
}
}
}
AccountFormController同时用于add account and edit account,但edit account需要先log in,而add account不需要,怎么办?
方案就是对于AccountFormController定义2个bean
<bean name="/shop/newAccount.do" class="org.springframework.samples.jpetstore.web.spring.AccountFormController">
<property name="petStore" ref="petStore"/>
<property name="validator" ref="accountValidator"/>
<property name="successView" value="index"/>
</bean>
<bean id="secure_editAccount" class="org.springframework.samples.jpetstore.web.spring.AccountFormController">
<property name="petStore" ref="petStore"/>
<property name="validator" ref="accountValidator"/>
<property name="successView" value="index"/>
</bean>
AbstractWizardFormController的运用
当你收集的info需要多个page的form来submit才行的话,就要用到AbstractWizardFormController。在jpetstore里,submit new order的Controller就是扩展AbstractWizardFormController。
submit new order的流程是:首先输入一些基本信息(如credit card no, billing address),同时还有一个check box “Ship to different address...”,如果钩上这个选项,按next,就会转到输入shipping address的form page,最后submit。如果没有钩上这个选项则跳过shipping address form page,直接submit.
下面看看OrderFormController的主要代码:
public class OrderFormController extends AbstractWizardFormController {
public OrderFormController() {
//设置多page form的所有page的name
setPages(new String[] {"NewOrderForm", "ShippingForm", "ConfirmOrder"});
}
。。。
//每个form page submit时,就都会调用该方法
//返回的是下一个page在pages array里的index
protected int getTargetPage(HttpServletRequest request, Object command, Errors errors, int currentPage) {
OrderForm orderForm = (OrderForm) command;
//如果钩上"Ship to different address..."选项,则跳到page 1,否则就跳到page 2
if (currentPage == 0 && orderForm.isShippingAddressRequired()) {
return 1;
}
else {
return 2;
}
}
//对于多form page的controller里如果使用validator,则应该在validatePage里进行(普通formController validate是在onBindAndValidate方法里进行)
protected void validatePage(Object command, Errors errors, int page) {
OrderForm orderForm = (OrderForm) command;
OrderValidator orderValidator = (OrderValidator) getValidator();
errors.setNestedPath("order");
switch (page) {
case 0:
orderValidator.validateCreditCard(orderForm.getOrder(), errors);
orderValidator.validateBillingAddress(orderForm.getOrder(), errors);
break;
case 1:
orderValidator.validateShippingAddress(orderForm.getOrder(), errors);
}
errors.setNestedPath("");
}
//最后一个form page submit时,调用该方法
protected ModelAndView processFinish(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
OrderForm orderForm = (OrderForm) command;
this.petStore.insertOrder(orderForm.getOrder());
request.getSession().removeAttribute("sessionCart");
Map model = new HashMap();
model.put("order", orderForm.getOrder());
model.put("message", "Thank you, your order has been submitted.");
return new ModelAndView("ViewOrder", model);
}
}
spring如何check form validate?
很简单,自己定义validator。在jpetstore里,AccountFormController and OrderFormController就会用到自定义的实现了validator接口的AccountValidator and OrderValidator。
public class AccountValidator implements Validator {
public boolean supports(Class clazz) {
return Account.class.isAssignableFrom(clazz);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "firstName", "FIRST_NAME_REQUIRED", "First name is required.");
。。。。
}
}
那么FormController如何插入validator?见bean定义:
<bean id="secure_editAccount" class="org.springframework.samples.jpetstore.web.spring.AccountFormController">
<property name="petStore" ref="petStore"/>
<property name="validator" ref="accountValidator"/>
<property name="successView" value="index"/>
</bean>
其中validator property不需要你的formController定义,而是扩展的SimpleFormController/AbstractWizardFormController本身就包含的property
那么FormController如何使用validator?见下列代码:
protected void onBindAndValidate(HttpServletRequest request,
Object command, BindException errors) throws Exception {
AccountForm accountForm = (AccountForm) command;
Account account = accountForm.getAccount();
if (request.getParameter("account.listOption") == null) {
account.setListOption(false);
}
if (request.getParameter("account.bannerOption") == null) {
account.setBannerOption(false);
}
errors.setNestedPath("account");
getValidator().validate(account, errors);
errors.setNestedPath("");
if (accountForm.isNewAccount()) {
account.setStatus("OK");
ValidationUtils.rejectIfEmpty(errors, "account.username",
"USER_ID_REQUIRED", "User ID is required.");
if (account.getPassword() == null
|| account.getPassword().length() < 1
|| !account.getPassword().equals(
accountForm.getRepeatedPassword())) {
errors
.reject(
"PASSWORD_MISMATCH",
"Passwords did not match or were not provided. Matching passwords are required.");
}
} else if (account.getPassword() != null
&& account.getPassword().length() > 0) {
if (!account.getPassword()
.equals(accountForm.getRepeatedPassword())) {
errors
.reject("PASSWORD_MISMATCH",
"Passwords did not match. Matching passwords are required.");
}
}
}
- spring + ibatis jpetstore 摘要
- 基于struts+spring+ibatis的 J2EE 开发(jpetstore分析)
- 运行ibatis jpetstore
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring+EasyJWeb+iBatis版j2ee在线购物jpetstore系统源码发布
- Spring JPetStore学习(一)配置JPetStore
- 正则表达式的JS验证!
- 使用java发送email
- 程序员的七种武器
- jquery使用方法简介
- sap视频教程
- spring + ibatis jpetstore 摘要
- 编写类String的构造函数,析构函数和赋值函数
- 关于对象的offsetWidht和offsetHeight
- vb6 GUid 生成
- Apache Tomcat 5.5 Servlet/JSP 容器安装 TOMCAT
- 中国地震带的分布
- 在spring2.5中无法使用dwr2
- 猴子摘桃程序
- 表格里的斜线,类似课程表的斜线