本文将以一个实际例子来讲解整合iBATIS和Spring在WEB开发中的应用。在例子中,将应用DAO,FACADE这些常用的设计模式。
1、需求说明
假定我们要实现一个用户注册和登录的需求。注册时将用户信息保存到数据库,登录时使用注册的信息进行校验。
2、数据库设计
我们建2个表,一个存放基本的用户信息(T_USERS),一个放附加的信息(T_USER_INFO)。这2个表是1对1的关系,其实可以只建一个表,但在实际的开发中,我们常常会把它们拆分,把常用的信息放到主表中,不常用的放到辅表中,这样可以提升性能。本文使用的数据库是ORACLE,表结构如下:
T_USERS 用户信息主表
字段名
字段说明
字段类型
userid
用户在系统中的流水号,为PRIMARY KEY
NUMBER(6,0) NOT NULL
ualias
用户别名,在登录时输入的名字
VARCHAR2(20) NOT NULL
password
密码
VARCHAR2(30) NULL
realname
真实姓名
VARCHAR2(20) NULL
VARCHAR2(30) NOT NULL
usertypeid
用户类型
CHAR(2) NOT NULL
SQL
CREATE TABLE T_USERS (
userid NUMBER(6,0) NOT NULL,
usertypeid CHAR(2) NOT NULL,
ualias VARCHAR2(20) NOT NULL,
password VARCHAR2(30) NULL,
email VARCHAR2(30) NOT NULL,
realname VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XAK1T_USERS ON T_USERS
( ualias ASC );
CREATE UNIQUE INDEX XAK2T_USERS ON T_USERS
( email ASC );
ALTER TABLE T_USERS ADD ( PRIMARY KEY (userid) ) ;
T_USER_INFO 用户信息辅表
字段名
字段说明
字段类型
userid
用户在系统中的流水号为KEY
NUMBER(6,0) NOT NULL
regdate
注册日期
DATE NULL
lastlogdate
最近一次登录日期
DATE NULL
logtimes
登录次数
NUMBER(6) NULL
SQL
CREATE TABLE T_USER_INFO (
userid NUMBER(6,0) NOT NULL,
regdate DATE NULL,
lastlogdate DATE NULL,
logtimes NUMBER(6) NULL
);
ALTER TABLE T_USER_INFO ADD ( PRIMARY KEY (userid) ) ;
ALTER TABLE T_USER_INFO ADD ( FOREIGN KEY (userid) REFERENCES T_USERS ) ;
SEQUENCE Sequence_userid 用户流水号产生
SQL
CREATE SEQUENCE Sequence_userid
INCREMENT BY 1
START WITH 1
MAXVALUE 999999
MINVALUE 1
NOCYCLE
NOORDER
;
3、构建源代码包目录
com(1)
|-wysm(2)
|-netstar(3)
|-domain(4) (POJO)
|-persistence(4) (持久化层)
|-iface(5) (DAO 接口)
|-sqlmapdao(5) (iBATIS DAO实现)
|-sql(6) (iBATIS sqlmap定义文件)
|-service(4) (FACADE接口)
|-ibatis(5) (FACADE iBATIS实现)
|-test(4)(JAVA环境测试)
4、iBATIS sqlmap定义
com.wysm.netstar.persistence.sqlmapdao.sql/sql-map-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource="com/wysm/netstar/properties/database.properties"/>
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property value="${driver}" name="JDBC.Driver"/>
<property value="${url}" name="JDBC.ConnectionURL"/>
<property value="${username}" name="JDBC.Username"/>
<property value="${password}" name="JDBC.Password"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/wysm/netstar/persistence/sqlmapdao/sql/User.xml"/>
<sqlMap resource="com/wysm/netstar/persistence/sqlmapdao/sql/Sequence.xml"/>
<sqlMap resource="com/wysm/netstar/persistence/sqlmapdao/sql/UserInfo.xml"/>
</sqlMapConfig>
数据库连接属性文件 com.wysm.netstar.properties.database.properties
####################################
# Database Connectivity Properties
####################################
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:ORA92SER
username=netstar
password=netstar
com.wysm.netstar.persistence.sqlmapdao.sql/Sequence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Sequence">
<select id="getSequenceUserId" resultClass="int">
select sequence_userid.nextval from dual
</select>
</sqlMap>
com.wysm.netstar.persistence.sqlmapdao.sql/User.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="User">
<typeAlias alias="user" type="com.wysm.netstar.domain.User"/>
<select id="getUserByUserAlias" resultClass="user" parameterClass="string">
SELECT
USERID as userId,
UALIAS as userAlias,
PASSWORD as password,
REALNAME as realName,
EMAIL as email,
USERTYPEID as userTypeId
FROM T_USERS
WHERE UALIAS = #userAlias#
</select>
<select id="getUserByUserAliasAndPassword" resultClass="user" parameterClass="user">
SELECT
USERID as userId,
UALIAS as userAlias,
PASSWORD as password,
REALNAME as realName,
EMAIL as email,
USERTYPEID as userTypeId
FROM T_USERS
WHERE UALIAS = #userAlias# AND
PASSWORD = #password#
</select>
<select id="getUserByEmail" resultClass="user" parameterClass="string">
SELECT
USERID as userId,
UALIAS as userAlias,
PASSWORD as password,
REALNAME as realName,
EMAIL as email,
USERTYPEID as userTypeId
FROM T_USERS
WHERE EMAIL=#email#
</select>
<update id="updateUser" parameterClass="user">
UPDATE T_USERS SET
UALIAS= #userAlias#,
PASSWORD=#password#,
REALNAME=#realName#,
EMAIL = #email#,
USERTYPEID = #userTypeId#
WHERE USERID = #userId#
</update>
<insert id="insertUser" parameterClass="user">
INSERT INTO T_USERS
(USERID,
UALIAS,
PASSWORD,
REALNAME,
EMAIL,
USERTYPEID)
VALUES
(#userId#, #userAlias#,#password#,#realName#, #email#, #userTypeId#)
</insert>
<delete id="deleteUser" parameterClass="int">
DELETE FROM T_USERS
WHERE USERID=#userId#
</delete>
<select id="existUserId" parameterClass="int">
select count(*) FROM T_USERS
WHERE USERID=#userId#
</select>
</sqlMap>
com.wysm.netstar.persistence.sqlmapdao.sql/UserInfo.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="User">
<typeAlias alias="userInfo" type="com.wysm.netstar.domain.UserInfo"/>
<select id="getUserInfoByUserId" resultClass="userInfo" parameterClass="int">
SELECT
USERID,
REGDATE,
LASTLOGDATE,
LOGTIMES
FROM T_USER_INFO
WHERE USERID = #userId#
</select>
<update id="updateUserInfo" parameterClass="userInfo">
UPDATE T_USER_INFO SET
REGDATE= #regDate#,
LASTLOGDATE=#lastLogDate#,
LOGTIMES=#logTimes#
WHERE USERID = #userId#
</update>
<insert id="insertUserInfo" parameterClass="userInfo">
INSERT INTO T_USER_INFO
(USERID,
REGDATE,
LASTLOGDATE,
LOGTIMES)
VALUES
(#userId#, #regDate#,#lastLogDate#,#logTimes#)
</insert>
<delete id="deleteUserInfo" parameterClass="int">
DELETE FROM T_USER_INFO
WHERE USERID=#userId#
</delete>
</sqlMap>
5、POJO定义
com.wysm.netstar.domain.User.java
package com.wysm.netstar.domain;
import java.io.*;
public class User implements Serializable {
private Integer userId;
private String userAlias;
private String password;
private String realName;
private String email;
private String userTypeId;
public User() {
}
public User(Integer userId) {
this.userId=userId;
}
public User(String userAlias) {
this.userAlias=userAlias;
}
public User(String userAlias,String password) {
this.userAlias=userAlias;
this.password=password;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public void setUserAlias(String userAlias) {
this.userAlias = userAlias;
}
public void setPassword(String password) {
this.password = password;
}
public void setUserTypeId(String userTypeId) {
this.userTypeId = userTypeId;
}
public void setRealName(String realName) {
this.realName = realName;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getUserId() {
return userId;
}
public String getUserAlias() {
return userAlias;
}
public String getPassword() {
return password;
}
public String getUserTypeId() {
return userTypeId;
}
public String getRealName() {
return realName;
}
public String getEmail() {
return email;
}
}
com.wysm.netstar.domain.UserInfo.java
package com.wysm.netstar.domain;
import java.util.*;
import java.io.Serializable;
public class UserInfo implements Serializable {
private Integer userId;
private Date regDate;
private Date lastLogDate;
private Integer logTimes;
public UserInfo() {
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public void setLastLogDate(Date lastLogDate) {
this.lastLogDate = lastLogDate;
}
public void setLogTimes(Integer logTimes) {
this.logTimes = logTimes;
}
public Integer getUserId() {
return userId;
}
public Date getRegDate() {
return regDate;
}
public Date getLastLogDate() {
return lastLogDate;
}
public Integer getLogTimes() {
return logTimes;
}
}
6、DAO接口定义
com.wysm.netstar.persistence.iface.BaseDao.java
package com.wysm.netstar.persistence.iface;
public interface BaseDao {
}
com.wysm.netstar.persistence.iface.SequenceDao.java
package com.wysm.netstar.persistence.iface;
public interface SequenceDao extends BaseDao {
Integer getSequenceUserId();
}
com.wysm.netstar.persistence.iface.UserDao.java
package com.wysm.netstar.persistence.iface;
import com.wysm.netstar.domain.User;
import java.util.List;
public interface UserDao extends BaseDao {
public abstract List getUser(String userAlias);
public abstract List getUserByEmail(String email);
public abstract List getUser(String userAlias,String password);
public abstract void insertUser(User user);
public abstract void updateUser(User user);
public abstract boolean existUserId(Integer userid);
}
com.wysm.netstar.persistence.iface.UserInfoDao.java
package com.wysm.netstar.persistence.iface;
import com.wysm.netstar.domain.UserInfo;
public interface UserInfoDao extends BaseDao {
public abstract UserInfo getUserInfo(Integer userId);
public abstract void insertUserInfo(UserInfo userInfo);
public abstract void updateUserInfo(UserInfo userInfo);
}
7、DAO iBATIS实现
com.wysm.netstar.persistence.sqlmapdao.BaseSqlMapDao.java
package com.wysm.netstar.persistence.sqlmapdao;
import com.ibatis.dao.client.DaoManager;
import com.ibatis.dao.client.template.SqlMapDaoTemplate;
public class BaseSqlMapDao extends SqlMapDaoTemplate {
protected static final int PAGE_SIZE = 4;
public BaseSqlMapDao(DaoManager daoManager) {
super(daoManager);
}
}
com.wysm.netstar.persistence.sqlmapdao.SequenceSqlMapDao.java
package com.wysm.netstar.persistence.sqlmapdao;
import com.ibatis.dao.client.DaoManager;
import com.wysm.netstar.persistence.iface.SequenceDao;
public class SequenceSqlMapDao extends BaseSqlMapDao implements SequenceDao {
public SequenceSqlMapDao(DaoManager daoManager) {
super(daoManager);
}
public Integer getSequenceUserId(){
return (Integer)queryForObject("getSequenceUserId",new Object());
}
}
com.wysm.netstar.persistence.sqlmapdao.UserSqlMapDao.java
package com.wysm.netstar.persistence.sqlmapdao;
import com.ibatis.dao.client.DaoManager;
import com.wysm.netstar.domain.User;
import com.wysm.netstar.persistence.iface.UserDao;
import java.util.List;
import org.apache.log4j.Logger;
public class UserSqlMapDao extends BaseSqlMapDao implements UserDao {
static Logger logger=Logger.getLogger(UserSqlMapDao.class);
public UserSqlMapDao(DaoManager daoManager) {
super(daoManager);
logger.debug("In UserSqlMapDao daoManager null="+(daoManager==null));
}
public List getUser(String userAlias){
return queryForList("getUserByUserAlias",userAlias);
}
public List getUser(String userAlias,String password){
User user=new User(userAlias,password);
return queryForList("getUserByUserAliasAndPassword",user);
}
public void insertUser(User user){
update("insertUser", user);
}
public void updateUser(User user){
update("updateUser", user);
}
public List getUserByEmail(String email){
return queryForList("getUserByEmail",email);
}
public boolean existUserId(Integer userid){
Integer cnt=(Integer)this.queryForObject("existUserId",userid);
return cnt.intValue()>0;
}
}
com.wysm.netstar.persistence.sqlmapdao.UserInfoSqlMapDao.java
package com.wysm.netstar.persistence.sqlmapdao;
import com.ibatis.dao.client.DaoManager;
import com.wysm.netstar.persistence.iface.UserInfoDao;
import com.wysm.netstar.domain.UserInfo;
public class UserInfoSqlMapDao extends BaseSqlMapDao implements UserInfoDao {
public UserInfoSqlMapDao(DaoManager daoManager) {
super(daoManager);
}
public UserInfo getUserInfo(Integer userId){
return (UserInfo)queryForObject("getUserInfoByUserId",userId);
}
public void insertUserInfo(UserInfo userInfo){
update("insertUserInfo", userInfo);
}
public void updateUserInfo(UserInfo userInfo){
update("insertUserInfo", userInfo);
}
}
8、Facade接口定义
com.wysm.netstar.persistence.sqlmapdao.UserInfoSqlMapDao.java
package com.wysm.netstar.service;
import com.wysm.netstar.domain.User;
public interface UserService {
public void addNewUser(User user);//增加新用户
public boolean existUserAlias(String userAlias);//检查用户别名是否已经存在
public User existUser(String userAlias,String password);//用户密码验证
public boolean existEmail(String email);//检查EMAIL是否已经存在
public boolean existUserId(Integer userId);//用户流水号验证
}
9、FACADE实现
com.wysm.netstar.service.ibatis.UserServiceImpl.java
package com.wysm.netstar.service.ibatis;
import java.util.*;
import org.apache.log4j.*;
import com.ibatis.dao.client.*;
import com.wysm.netstar.domain.*;
import com.wysm.netstar.persistence.iface.*;
import com.wysm.netstar.service.*;
public class UserServiceImpl implements UserService {
private UserDao userDao;
private SequenceDao sequenceDao;
private UserInfoDao userInfoDao;
private DaoManager daoMgr;
static Logger logger=Logger.getLogger(UserServiceImpl.class);
public UserServiceImpl() {
// daoMgr = DaoConfig.getDaoManager();
// this.userDao=(UserDao)daoMgr.getDao(UserDao.class);
}
private void initDaos(){
if (userDao==null){
this.userDao=(UserDao)daoMgr.getDao(UserDao.class);
this.sequenceDao=(SequenceDao)daoMgr.getDao(SequenceDao.class);
this.userInfoDao=(UserInfoDao)daoMgr.getDao(UserInfoDao.class);
}
}
public void addNewUser(User user){
Integer id=sequenceDao.getSequenceUserId();
user.setUserId(id);
UserInfo userInfo=new UserInfo();
userInfo.setUserId(id);
userInfo.setLastLogDate(null);
userInfo.setLogTimes(new Integer(0));
userInfo.setRegDate(new Date());
try{
daoMgr.startTransaction();
userDao.insertUser(user);
userInfoDao.insertUserInfo(userInfo);
daoMgr.commitTransaction();
}catch(Exception ex){
ex.printStackTrace();
}finally{
daoMgr.endTransaction();
}
}
public boolean existUserAlias(String userAlias){
List users=userDao.getUser(userAlias);
if (users!=null&&users.size()>0)
return true;
return false;
}
public User existUser(String userAlias,String password){
List users=userDao.getUser(userAlias,password);
if (users!=null&&users.size()>0)
return (User)users.get(0);
return null;
}
public boolean existEmail(String email){
List users=userDao.getUserByEmail(email);
if (users!=null&&users.size()>0)
return true;
return false;
}
public void setDaoMgr(DaoManager daoMgr) {
this.daoMgr = daoMgr;
}
public void setSequenceDao(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setUserInfoDao(UserInfoDao userInfoDao) {
this.userInfoDao = userInfoDao;
}
public boolean existUserId(Integer userId){
if (userId.intValue()==0)
return false;
return userDao.existUserId(userId);
}
}
10、iBATIS DAO支持定义
com.wysm.netstar.persistence/dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE daoConfig
PUBLIC "-//ibatis.apache.org//DTD DAO Configuration 2.0//EN"
"http://ibatis.apache.org/dtd/dao-2.dtd">
<daoConfig>
<context>
<transactionManager type="SQLMAP">
<property name="SqlMapConfigResource"
value="com/wysm/netstar/persistence/sqlmapdao/sql/sql-map-config.xml"/>
</transactionManager>
<dao interface="com.wysm.netstar.persistence.iface.UserDao"
implementation="com.wysm.netstar.persistence.sqlmapdao.UserSqlMapDao"/>
<dao interface="com.wysm.netstar.persistence.iface.SequenceDao"
implementation="com.wysm.netstar.persistence.sqlmapdao.SequenceSqlMapDao"/>
<dao interface="com.wysm.netstar.persistence.iface.UserInfoDao"
implementation="com.wysm.netstar.persistence.sqlmapdao.UserInfoSqlMapDao"/>
</context>
</daoConfig>
com.wysm.netstar.persistence.DaoConfig.java
package com.wysm.netstar.persistence;
import com.ibatis.common.resources.Resources;
import com.ibatis.dao.client.DaoManager;
import com.ibatis.dao.client.DaoManagerBuilder;
import java.io.Reader;
import java.util.Properties;
import org.apache.log4j.Logger;
public class DaoConfig {
private static final String resource = "com/wysm/netstar/persistence/dao.xml";
private static final DaoManager daoManager;
static Logger logger=Logger.getLogger(DaoConfig.class);
static {
try {
daoManager = newDaoManager(null);
} catch (Exception e) {
throw new RuntimeException("Description. Cause: " + e, e);
}
}
public static DaoManager getDaoManager() {
return daoManager;
}
public static DaoManager newDaoManager(Properties props) {
try {
Reader reader = Resources.getResourceAsReader(resource);
return DaoManagerBuilder.buildDaoManager(reader, props);
} catch (Exception e) {
throw new RuntimeException("Could not initialize DaoConfig. Cause: " + e, e);
}
}
}
11、Spring Bean定义文件
applicationContext.xml这个文件应该放在WEB包的 WEB-INF/下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="daoManager" class="com.wysm.netstar.persistence.DaoConfig" factory-method = "getDaoManager"/>
<bean id="sequenceDao" class="com.wysm.netstar.persistence.iface.SequenceDao" factory-bean = "daoManager" factory-method="getDao">
<constructor-arg>
<value>com.wysm.netstar.persistence.iface.SequenceDao</value>
</constructor-arg>
</bean>
<bean id="userDao" class="com.wysm.netstar.persistence.iface.UserDao" factory-bean = "daoManager" factory-method="getDao">
<constructor-arg>
<value>com.wysm.netstar.persistence.iface.UserDao</value>
</constructor-arg>
</bean>
<bean id="userInfoDao" class="com.wysm.netstar.persistence.iface.UserInfoDao" factory-bean = "daoManager" factory-method="getDao">
<constructor-arg>
<value>com.wysm.netstar.persistence.iface.UserInfoDao</value>
</constructor-arg>
</bean>
<bean name="userService" class="com.wysm.netstar.service.ibatis.UserServiceImpl" singleton="false">
<property name="daoMgr">
<ref bean="daoManager"/>
</property>
<property name="sequenceDao">
<ref bean="sequenceDao"/>
</property>
<property name="userDao">
<ref bean="userDao"/>
</property>
<property name="userInfoDao">
<ref bean="userInfoDao"/>
</property>
</bean>
<bean name="userService" class="com.wysm.netstar.service.ibatis.UserServiceImpl" singleton="false">
<property name="daoMgr">
<ref bean="daoManager"/>
</property>
<property name="sequenceDao">
<ref bean="sequenceDao"/>
</property>
<property name="userDao">
<ref bean="userDao"/>
</property>
<property name="useInfoDao">
<ref bean="useInfoDao"/>
</property>
</bean>
</beans>
12、在JAVA环境下测试以上内容
com.wysm.netstar.test.SpringTestCase.java
package com.wysm.netstar.test;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.wysm.netstar.actions.CatalogAction;
import com.wysm.netstar.service.UserService;
import com.wysm.netstar.domain.Catalog;
import java.util.List;
public class SpringTestCase extends TestCase {
private UserService userService;
private Catalog catalog;
protected void setUp() throws Exception {
super.setUp();
ApplicationContext ctx=new FileSystemXmlApplicationContext( "D:/JBProject/NetStarv0.1/netstar/WEB-INF/applicationContext.xml");
userService =(UserService)ctx.getBean("UserService");
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testSave(){
//自己写测试代码
}
}
(累死我了,讲解内容以后有空再写吧)