有关于示例本身 ( 基础代码源自 learntechnology ,结合自己的习惯有较多改进 )
表设计 PDM :
所涉及的页面:浏览员工的页面 employee_list.jsp
增加 / 编辑员工信息的页面 employee_add.jsp
学习笔记:
Ibatis 方面:如果要把 ibatis 引入到项目中来,需要做以下方面的工作。
* If you want to use bytecode enhancement for advanced lazy loading:
CGLIB 2.0 (http://cglib.sf.net)
* If you want to use the Jakarta DBCP connection pool you'll need:
DBCP 1.1 (http://jakarta.apache.org/commons/dbcp/)
* If you want to use distributed caching you'll need:
OSCache 2.0.1 (http://www.opensymphony.com/oscache/)
* If you want to use advanced logging you'll need one or both of the following:
Commons Logging (http://jakarta.apache.org/commons/)
Log4J 1.2.8 (http://logging.apache.org/log4j/docs/)
That's it!
Ibatis 基础配置文件:文件名 , 位置可以任意,一般为 SqlMapConfig.xml
1
<? xml version="1.0" encoding="UTF-8" ?>
2 <! DOCTYPE sqlMapConfig 3 PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" 4 "http://www.ibatis.com/dtd/sql-map-config-2.dtd" > 5 6 < sqlMapConfig > 7 < properties resource ="jdbc.properties" /> 8 < settings 9 cacheModelsEnabled ="true" 10 enhancementEnabled ="true" 11 useStatementNamespaces ="true" 12 lazyLoadingEnabled ="true" 13 errorTracingEnabled ="true" 14 maxRequests ="32" 15 maxSessions ="10" 16 maxTransactions ="5" 17 /> 18 19 < transactionManager type ="JDBC" > 20 < dataSource type ="DBCP" > 21 < property name ="JDBC.Driver" value ="${driver}" /> 22 < property name ="JDBC.ConnectionURL" value ="${jdbcURL}" /> 23 < property name ="JDBC.Username" value ="${username}" /> 24 < property name ="JDBC.Password" value ="${password}" /> 25 < property name ="Pool.MaximumWait" value ="30000" /> 26 < property name ="Pool.ValidationQuery" value ="select 1 from employee" /> 27 < property name ="Pool.LogAbandoned" value ="true" /> 28 < property name ="Pool.RemoveAbandonedTimeout" value ="1800000" /> 29 < property name ="Pool.RemoveAbandoned" value ="true" /> 30 </ dataSource > 31 </ transactionManager > 32 33 < sqlMap resource ="ibatis/demo/dao/Employee.xml" /> 34 < sqlMap resource ="ibatis/demo/dao/Department.xml" /> 35 36 </ sqlMapConfig > 37
以上各参数的涵义及默认值见 ibatsi 官方文档: iBATIS-SqlMaps-2_en.pdf
iBATIS 基础 dao 启动类
1 public class BaseIbatisDao {
2 3 private static BaseIbatisDao instance = new BaseIbatisDao(); 4 5 private static Logger log = Logger.getLogger(BaseIbatisDao.class.getName()); 6 7 protected static final SqlMapClient sqlMap; 8 9 static { 10 11 try { 12 13 log.debug("Attempting to initialize SqlMap"); 14 15 String resource = "ibatis/demo/dao/SqlMapConfig.xml"; 16 17 Reader reader = Resources.getResourceAsReader(resource); 18 19 sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); 20 21 log.debug("Initialized SqlMap"); 22 23 } catch (Exception e) { 24 25 log.error("Error intializing BaseIbatisDao ", e); 26 27 e.printStackTrace(); 28 29 throw new RuntimeException("Error initializing BaseIbatisDao class. Cause: " + e); 30 31 } 32 33 } 34 35 protected BaseIbatisDao() { 36 37 } 38 39 public static BaseIbatisDao getInstance() { 40 41 return instance; 42 43 } 44 45 } 46 项目中的 dao 实现类均继承该 dao 类,调用该类中 SqlMapClient sqlMap 上的各种方法可进行 CRUD 等操作。 sqlMap.queryForList("Employee.getAll", null); emp = (Employee) sqlMap.queryForObject("Employee.getById", id); sqlMap.delete("Employee.delete", id); sqlMap.update("Employee.update", employee); sqlMap.insert("Employee.insert", employee);
iBATIS 典型的 O/R 映射文件配置 Employee.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> 3 <sqlMap namespace="Employee"> 4 5 <typeAlias type="ibatis.demo.vo.Employee" alias="emp"/> 6 <cacheModel id="employeesCache" type="MEMORY" readOnly="false" serialize="true"> 7 <flushInterval hours="24"/> 8 <flushOnExecute statement="Employee.update"/> 9 <flushOnExecute statement="Employee.insert"/> 10 <flushOnExecute statement="Employee.delete"/> 11 </cacheModel> 12 13 <resultMap id="employeeResult" class="emp"> 14 <result property="id" column="id"/> 15 <result property="firstName" column="firstname"/> 16 <result property="lastName" column="lastname"/> 17 <result property="age" column="age"/> 18 <result property="department.id" column="dept_id"/> 19 <result property="department.name" column="name"/> 20 </resultMap> 21 22 <select id="getAll" resultClass="java.util.HashMap" cacheModel="employeesCache"> 23 SELECT 24 e.id AS id, 25 e.firstname AS firstName, 26 e.lastname AS lastName, 27 e.age AS age, 28 d.id AS deptId, 29 d.name AS deptName 30 FROM employee e, department d 31 WHERE e.dept_id = d.id 32 </select> 33 34 <!-- the alias in the following select must match the above employeeResult 'column'! --> 35 <select id="getById" resultMap="employeeResult" parameterClass="java.lang.Integer"> 36 SELECT 37 e.id, 38 e.firstname, 39 e.lastname, 40 e.age, 41 d.id AS dept_id, 42 d.name AS name 43 FROM employee e, department d 44 WHERE e.id = #value# 45 AND e.dept_id = d.id 46 </select> 47 48 <update id="update" parameterClass="emp"> 49 UPDATE employee 50 SET 51 firstname = #firstName#, 52 lastname = #lastName#, 53 age = #age#, 54 dept_id = #department.id# 55 WHERE employee.id = #id# 56 </update> 57 58 <insert id="insert" parameterClass="emp"> 59 INSERT INTO employee ( id, firstname, lastname, age, dept_id ) 60 VALUES ( null, #firstName#, #lastName#, #age#, #department.id# ) 61 </insert> 62 63 <delete id="delete" parameterClass="java.lang.Integer"> 64 DELETE FROM employee WHERE employee.id = #value# 65 </delete> 66 67 </sqlMap> 68
Struts 学习笔记: Struts-config.xml 的位置可以和其它所有的配置文件一起放到 WEB-INF/classes 目录下便于集中管理。
ActionForm 和 VO 之间数值的传递 添加的时候从 ActionForm 到 VO BeanUtils.copyProperties(employee, employeeForm) 而编辑的时候从 VO 到 ActionForm BeanUtils.copyProperties(employeeForm, employee);
页面中使用 struts 标签和 JSTL,EL 标签的好处 , 1 . URL 前面不用加上 contextRoot 的名字,便于项目的移植 eg: <link href="<c:url value='/css/main.css'/>" rel="stylesheet" type="text/css" />
eg: <html:form action="/employee">
< c:url var = "url" scope = "page" value = "/employee.do" > < c:param name = "p" value = "addOrUpdateIn" /> </ c:url > < a href = " ${url}">Add New Employee</a>
2 . <html:text > 标签具有数值自动绑定的功能,无需使用 <input> 中的 value ,在编辑记录或提交记录出错时,原有表单数据不会丢失 <html:text property="age" size="10"/>
3 .在 ActionForm 中添加错误信息可以使用 errors.add("age", new ActionMessage("errors.number", "Age")); 其中 age 表示取出消息的键值, errors.number 是 i18N 文件中的那句, Age 是那句的参数占位符,可以设计一个通用的 BaseAction, 增加一个写入消息的方法 可以在页面中以如下方式取出 <html:errors property="age"/> 或 <html:messages id="info"> <bean:write name="info" /> </html:messages> 或 4, 在 actionForm 中可以使用复合类型的数据 public class EmployeeForm extends BaseForm { String id; String firstName; String lastName; String age; Department department; // 使用复合类型
在 JSP 中存取复合类型数据时,可以使用打 . 的方式 以前项目中的写法: <SELECT name="category_id"> <c:forEach items="${categorys}" var="category"> <OPTION value="${category.id}" <c:if test="${category == blog.category}">selected="selected"</c:if>> ${category.name} </OPTION> </c:forEach> </SELECT> 改进后的写法 ( 再不用做 if 判断了 !) < html:select property = "department.id" > < c:forEach var = "dept" items = " ${departments}"> < html:option value = " ${dept.id}"> ${dept.name} </ html:option > </ c:forEach > </ html:select >
其它: 关于业务异常 BusinessException, 应设计为 unchecked Exception 在 dao 层的实现类中抛出 在 service 层的接口上声明 在 struts action 中的关键方法如 addOrUpdate, delete 中捕获 这一步将会增加许多无关代码,应该放到最后。
如果不使用 ant, 而直接使用 MyEclipse 发布,方法是 MyEclipse->Add Web Capability -> 填写 contextRoot -> 取消create web.xml 前面的小勾, OK © |