上一篇中介绍了用maven快速生成一个struts2骨架程序,接下来要连接数据库了,这个过程中也遇到了很多问题和解决问题的心得体会
2.数据库链接
小系统中采用的是mysql数据库,至于为什么选用,呵呵,开源,系统资源占用小,用的也很广泛,所以借此机会重新回归一下还是有意义的
2.1数据库建表
上一篇分析过了,系统中就3个对象User,App,Isv,很简单的三张表,每个对象的属性也不多,5-6个的样子,所以不再罗列
2.2关于数据库命名规范
2.2.1字段命名
1)表名与对象名保持一致分别为user,app,isv,表的字段名与对象属性保持一致,如user表里name,password,而没有采用user_name,user_password的格式来,这也是先前DBA同学推荐的格式
2)字段长度尽量设计与实际的长度和类型保持一致,如name字段最大长度设计为32就可以了,可空字段不要设置缺省值
3)每个表都增加gmt_create和gmt_modified字段,这也是在公司做所有大型商业项目时必须要求做到的,一个表不加这两个字段DBA是不会给你创建表的,用这两个字段分别表示记录的创建时间和最后修改时间,这两个字段没有任何业务含义
4)数据库名,表名,字段名统一大小写,字段,表名或字段名全部英文,多个单词中间用'_'分隔
5)忘记外键--这个是整个公司都在实行的,貌似和我们大学的课本上的那一堆的范式有冲突,呵呵,数据上的一致性靠程序逻辑去保证,而不可能是依靠数据库报错来决定,app应用表里有个isv_id字段表示该应用是属于哪个开发者的,这个字段是和isv开发者表里的主键id是一致的,这里不设置外键关联关系,程序上去保证完整性
2.3Ibatis集成
1)导入Ibatis的jar包
好了,数据库表搭建ok了,程序也有了,该是ibatis出马的时候了,再次展示了maven的伟大,eclipse插件里maven-->add dependency,输入ibatis,选择2.0版本的ibatis,一些依赖的jar包自动添加到应用的classpath中~
2)创建数据库到java对象的映射
设计的domain对象还是贫血模型,都是简单的java bean,对象中的属性和数据库表中的属性是一一对应的,如User对象的java类位于
scr/main/java/com/taobao/top/coreapp/domain/user/UserInfo.java
Ibatis是个很优秀的or mapping框架,他核心的功能就是把你的java对象和表字段映射关联起来,在这里我们采用的是每个表一个Ibatis映射文件的配置方式,配置文件的存放路径和对应java代码的包路径保持一致,但配置文件都统一放在src/main/resources目录下,如src/main/resources/scr/main/java/com/taobao/top/coreapp/domain/user/UserInfo.xml
3)User.xml文件中的玄机
<sqlMap namespace="UserInfo"> --定义一个namespace,可以减少不同sql map配置文件中包含相同id的sql而造成执行出错的问题
<typeAlias alias="UserInfoAlias" type="com.taobao.top.coreapp.domain.user.UserInfo" />
--为这个爆长的类名取个别名,这样应用起来直接写简短的别名就ok了
<resultMap id="UserInfoResult" class="UserInfoAlias">
--java bean与表字段的映射对应关系,这个class指向的就是上一行的aliais,一个统一规范的命名也能减少理解的成本
<result property="id" column="ID" />
<result property="name" column="NAME" />
--注意,在映射时数据库字段名称是不区分大小写的
<result property="password" column="PASSWORD" />
<result property="nick" column="NICK" />
<result property="gmtCreate" column="GMT_CREATE" />
<result property="gmtModified" column="GMT_MODIFIED" />
</resultMap>
<!-- 通过用户ID获取用户信息 --> --为每个sql写上简短的注释
<select id="getUserById" parameterClass="long" resultMap="UserInfoResult">
--sql语句的id和dao中的方法名是一致的,如这条sql是 UserInfoDAO.getUserById中调用的
<![CDATA[
--统一把sql语句都用<![[]]包裹起来,因为有时候sql中会有一些比较特殊的字符 < >等,编辑器会误认为是元素的开始/结束符号,导致编辑器报错的情况
SELECT
id
,name
,password
,nick
,gmt_create
--sql语句的写法尊需严格的缩进,这样看起来层次比较分明,可以下载一个eclipse db viewer的插件,该插件还提供了格式化sql语句的功能
,gmt_modified
--sql字段的名字必须严格区分大小写,我先前试过把字段改成大写,结果就报错找不到字段(我用的是Ubuntu系统,windows下是没问题的,这个一定要注意)
FROM
users
WHERE
id = #id#
]]>
</select>
其他的几个sql文件也遵照同样的格式和规范来执行,然后统一在sqlMapConfig.xml中声明一下就可以啦
<sqlMapConfig>
<sqlMap resource="com/taobao/top/coreapp/domain/user/UserInfo.xml" />
<sqlMap resource="com/taobao/top/coreapp/domain/isv/IsvInfo.xml" />
<sqlMap resource="com/taobao/top/coreapp/domain/app/AppInfo.xml"/>
</sqlMapConfig>
4)把sqlMapConfig.xml交给spring吧
好了,数据库有了,表有了,java对象有了,表和对象的映射关系也有了,是时候让spring把各个东东搞到一起的时候了
1)配置数据源datasource
在系统中一般都用数据源的方式来链接数据库,这里采用的是apache的dbcp数据源,spring中配置一下各个属性就可以了,记得把数据库的密码,用户名,地址之类的提取到.properties文件中存放是一个很好的时间方式啊
2)让spring找到你的sqlMapConfig.xml
配置一个SqlMapClient bean,让location指向配置文件,然后记得把数据源注入进来,这样就把ibatis交给spring了
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
2)程序中如何调用biatis的接口来操作sql呢?
Spring是一个设计很优雅的框架,对各种主流的orm框架也提供了很好的支持,通常我们只要继承一下
org.springframework.orm.ibatis.support.SqlMapClientDaoSupport类就可以调用该类中的方法来操作数据库了,这个类有个sqlMapClient属性,只要吧这个对象注入一下就可以用了。
这里有个问题,就是我有3个dao的实现类,如果每个实现类都要继承一下这个类,然后每个实现类的spring中去注入这样一个属性太繁琐了,有没有什么方式可以简化配置呢?
当然是可以的,配置一个BaseSpringDAO,用来注入一些所有dao类都需要用到的东西,如dataSource对象,达到的效果就是,这些通用属性的注入主要在父类中注入一次,各个子类只要继承一下父类的配置就可以获得父类中注入的属性了,这样会极大的家少重复代码
类的继承结构&spring中的配置
<!-- 所有DAO的基类,用来注入dataSource数据源 -->
<bean id="baseDAO" class="com.taobao.top.coreapp.dao.BaseSpringDAOIbatis"
abstract="true"> --这种bean一般都声明为abstract抽象的,就是专门用来继承用的
<property name="dataSource" ref="dataSource"></property>
<property name="sqlMapClient" ref="sqlMapClient"></property>
</bean>
<!-- 用户信息DAO类 -->
<bean id="userInfoDAO"
class="com.taobao.top.coreapp.dao.user.ibatis.UserInfoDAOIbatis"
parent="baseDAO" />
--这个parent指向父类,这样就把父类注入的属性都继承下来了