1
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
<? xml version="1.0" encoding="UTF-8" ?>
2
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
<! DOCTYPE sqlMapConfig
3
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
4
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
"http://www.ibatis.com/dtd/sql-map-config-2.dtd" >
5
6
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< sqlMapConfig >
7
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< properties resource ="jdbc.properties" />
8
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< settings
9
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
cacheModelsEnabled ="true"
10
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
enhancementEnabled ="true"
11
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
useStatementNamespaces ="true"
12
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
lazyLoadingEnabled ="true"
13
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
errorTracingEnabled ="true"
14
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
maxRequests ="32"
15
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
maxSessions ="10"
16
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
maxTransactions ="5"
17
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
/>
18
19
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< transactionManager type ="JDBC" >
20
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< dataSource type ="DBCP" >
21
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="JDBC.Driver" value ="${driver}" />
22
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="JDBC.ConnectionURL" value ="${jdbcURL}" />
23
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="JDBC.Username" value ="${username}" />
24
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="JDBC.Password" value ="${password}" />
25
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="Pool.MaximumWait" value ="30000" />
26
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="Pool.ValidationQuery" value ="select 1 from employee" />
27
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="Pool.LogAbandoned" value ="true" />
28
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="Pool.RemoveAbandonedTimeout" value ="1800000" />
29
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< property name ="Pool.RemoveAbandoned" value ="true" />
30
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
</ dataSource >
31
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
</ transactionManager >
32
33
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< sqlMap resource ="ibatis/demo/dao/Employee.xml" />
34
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
< sqlMap resource ="ibatis/demo/dao/Department.xml" />
35
36
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
</ 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
以上配置中各参数用法涵义见
iBATIS 官方文档。需要注意的问题 , 用 ## 包裹的是 bean 中 property 的名字,要特别注意 <select> 标签中取出的字段名或别名和 resultMap , resultClass 及在 JSP 页面取出这些数据时的命名关系
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>
eg: <html:link page="/employee.do?p=chart">View Chart</html:link>
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>
或
<html:messages id="info">
<c:out value="${info}" escapeXml="false" />
</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 ©
![ibatis_project.jpg](https://i-blog.csdnimg.cn/blog_migrate/7150231038a471d4539149216b9637d4.jpeg)