20. 三层架构中的 MVC Web 应用程序 – 示例 6,SQL Server Express
20.1. SQL Server Express 数据库
在此版本中,我们将人员列表存储在 SQL Server Express 2005 数据库表中,该表可通过 URL [http://msdn.microsoft.com/vstudio/express/sql/] 访问。以下屏幕截图来自 EMS Manager Lite for SQL Server Express [http://www.sqlmanager.net/fr/products/mssql/manager],这是一个用于 SQL Server Express 数据库管理系统(DBMS)的免费管理客户端。
该数据库名为 [dbpersonnes]。其中包含一个名为 [PERSONNES] 的表:

[PERSONNES] 表将包含由 Web 应用程序管理的人员列表。该表是通过以下 SQL 语句创建的:
- 第 2 行:主键 [ID] 的类型为整数。IDENTITY 属性表示,如果插入一行时未为表的 ID 列指定值,SQL Express 将自动为该列生成一个整数。在 IDENTITY(1, 1) 中,第一个参数是主键的起始值,第二个参数是生成数字时使用的增量。
[PERSONS] 表可能包含以下内容:

我们知道,当通过 [DAO] 层插入 [Person] 对象时,该对象的 [id] 字段在插入前等于 -1,插入后则取其他值;该值即为插入到 [PERSONNES] 表的新行所分配的主键。让我们通过一个示例来了解如何确定该值。
![]() |
![]() |
SQL语句
会返回插入到表的 ID 字段中的最后一个值。该语句应在插入操作之后执行。这与 [Firebird] 和 [Postgres] 数据库管理系统不同,后者是在插入之前查询已添加记录的主键值,但它与 MySQL 数据库管理系统中的主键生成机制类似。 我们将在 [people-sqlexpress.xml] 文件中使用它,该文件包含在数据库上执行的 SQL 语句。
20.2. 用于 [DAO] 和 [service] 层的 Eclipse 项目
为了使用 [SQL Server Express] 数据库开发应用程序的 [DAO] 和 [service] 层,我们将使用以下 Eclipse 项目 [mvc-personnes-06]:

该项目是一个简单的 Java 项目,而非 Tomcat Web 项目。
[src] 文件夹
该文件夹包含 [dao] 和 [service] 层的源代码:

所有文件名中包含 [sqlexpress] 的文件,与 Firebird、Postgres 和 MySQL 版本相比,可能已被修改,也可能未被修改。下文仅描述那些已被修改的文件。
[database] 文件夹
此文件夹包含用于创建 SQL Express 数据库的脚本:
![]()
[lib] 文件夹
此文件夹包含应用程序所需的资源包:
![]() |
请注意,这里包含用于数据库管理系统 [SQL Server Express] 的 JDBC 驱动程序 [sqljdbc.jar]。所有这些文件均属于 Eclipse 项目的类路径。
20.3. [DAO] 层
[DAO] 层如下所示:

我们仅突出显示了与 [Firebird] 版本相比的变更。
映射文件 [personne-sqlexpress.xml] 如下所示:
<?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>
<!-- alias class [Person] -->
<typeAlias alias="Personne.classe"
type="istia.st.mvc.personnes.entites.Personne"/>
<!-- mapping table [PERSONNES] - object [Person] -->
<resultMap id="Personne.map"
class="istia.st.mvc.personnes.entites.Personne">
<result property="id" column="ID" />
<result property="version" column="VERSION" />
<result property="nom" column="NOM"/>
<result property="prenom" column="PRENOM"/>
<result property="dateNaissance" column="DATENAISSANCE"/>
<result property="marie" column="MARIE"/>
<result property="nbEnfants" column="NBENFANTS"/>
</resultMap>
<!-- list of all persons -->
<select id="Personne.getAll" resultMap="Personne.map" > select ID, VERSION, NOM,
PRENOM, DATENAISSANCE, MARIE, NBENFANTS FROM PERSONNES</select>
<!-- get a specific person -->
<select id="Personne.getOne" resultMap="Personne.map" >select ID, VERSION, NOM,
PRENOM, DATENAISSANCE, MARIE, NBENFANTS FROM PERSONNES WHERE ID=#value#</select>
<!-- add a person -->
<insert id="Personne.insertOne" parameterClass="Personne.classe">
insert into
PERSONNES(VERSION, NOM, PRENOM, DATENAISSANCE, MARIE, NBENFANTS)
VALUES(#version#, #nom#, #prenom#, #dateNaissance#, #marie#,
#nbEnfants#)
<selectKey keyProperty="id">
select @@IDENTITY as value
</selectKey>
</insert>
<!-- update a person -->
<update id="Personne.updateOne" parameterClass="Personne.classe"> update
PERSONNES set VERSION=#version#+1, NOM=#nom#, PRENOM=#prenom#, DATENAISSANCE=#dateNaissance#,
MARIE=#marie#, NBENFANTS=#nbEnfants# WHERE ID=#id# and
VERSION=#version#</update>
<!-- delete a person -->
<delete id="Personne.deleteOne" parameterClass="int"> delete FROM PERSONNES WHERE
ID=#value# </delete>
<!-- obtain the value of the primary key [id] of the last person inserted -->
<select id="Personne.getNextId" resultClass="int">select
LAST_INSERT_ID()</select>
</sqlMap>
这与 [people-firebird.xml] 的内容相同,仅有以下细微差异:
- 第 29–37 行中的 SQL 语句 "Person.insertOne" 已发生变更:
- SQL插入语句在SELECT语句之前执行,该SELECT语句用于检索已插入行主键的值
- SQL 插入语句未为 [PERSONNES] 表中的 ID 列指定值
这反映了我们在第 20.1 节中讨论的插入示例。请注意,第 19.3 节中针对 MySQL 描述的不同线程同时插入的问题,在此处同样存在。
[dao] 层的实现类 [DaoImplCommon] 与前三个版本中的相同。
[dao]层的配置已针对[SQL Express]数据库管理系统进行了调整。因此,配置文件[spring-config-test-dao-sqlexpress.xml]如下所示:
<?xml version="1.0" encoding="ISO_8859-1"?>
<!DOCTYPE beans SYSTEM "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- data source DBCP -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>com.microsoft.sqlserver.jdbc.SQLServerDriver</value>
</property>
<property name="url">
<value>jdbc:sqlserver://localhost\\SQLEXPRESS:4000;databaseName=dbpersonnes</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value>msde</value>
</property>
</bean>
<!-- SqlMapCllient -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="configLocation">
<value>classpath:sql-map-config-sqlexpress.xml</value>
</property>
</bean>
<!-- the [dao] layer access classes -->
<bean id="dao" class="istia.st.mvc.personnes.dao.DaoImplCommon">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>
</beans>
- 第 5-19 行:[dataSource] Bean 现指向 [SQL Express] 数据库 [dbpersonnes],其管理员为 [sa],密码为 [msde]。读者应根据自身环境修改此配置。
- 第 31 行:[DaoImplCommon] 类是 [dao] 层的实现类
第 11 行需要稍作说明:
<value>jdbc:sqlserver://localhost\\SQLEXPRESS:4000;databaseName=dbpersonnes</value>
- //localhost: 表示 SQL Express 服务器与我们的 Java 应用程序位于同一台机器上
- \\SQLEXPRESS: 是 SQL Server 实例的名称。由于多个实例可以同时运行,因此明确指定要连接的具体实例名称是合理的。该名称可通过 [SQL Server 配置管理器] 获取,该工具通常随 SQL Express 一起安装:


- 4000:SQL Express 的监听端口。该端口取决于服务器配置。默认情况下,它使用动态端口,这些端口无法提前确定。在这种情况下,JDBC URL 中不指定端口。在此,我们使用了固定端口 4000。该端口是通过配置设置的:
![]() |
- dataBaseName 属性指定要操作的数据库。这是使用 EMS 客户端创建的数据库:

完成这些修改后,我们可以进行测试。
20.4. 针对 [dao] 和 [service] 层的测试
针对 [dao] 和 [service] 层的测试与 [Firebird] 版本的测试相同。所得结果如下:
![]() |
我们可以看到,使用 [DaoImplCommon] 实现时测试已成功通过。与 [Firebird] 数据库管理系统(DBMS)的情况不同,我们无需派生该类。
20.5. [Web] 应用程序测试
为了使用 [SQL Server Express] 数据库管理系统测试 Web 应用程序,我们将按照与构建先前 Web 项目类似的方式,构建一个 Eclipse 项目 [mvc-personnes-06B]。
我们将 Web 项目 [mvc-personnes-05B] 部署到 Tomcat 中:
![]() | ![]() |
SQL Server Express 数据库管理系统已启动。此时 [PERSONNES] 表的内容如下:

随后启动 Tomcat。使用浏览器访问 URL [http://localhost:8080/mvc-personnes-06B]:

我们通过 [添加]链接添加了一位新用户:
![]() | ![]() |
我们在数据库中验证新增记录:

欢迎读者进行其他测试 [编辑、删除]。








