本文将以一个实际例子来讲解整合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 |
email |
email |
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("Descrīption. 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(){ //自己写测试代码 } }
| |