mule的jdbc transport功能过于简单, 今天的需求是把ibatis集成进来, 作为一个service的component, 以增强持久层功能.
mule可以直接引用spring的配置文件, 方法如下:
<spring:beans> <spring:import resource="applicationContext.xml" /> <spring:import resource="applicationContext-ibatis.xml" /> </spring:beans>
作为一个演示,我需要往一个vm:queue中写入消息,component(由spring bean充当) 得到消息, 并作为查询参数 从数据库查询数据并返回.
model定义如下:
<model name="databaseModel"> <service name="databaseUMO"> <!-- any number of endpoints can be added to an inbound router --> <inbound> <vm:inbound-endpoint path="query" /> </inbound> <component> <method-entry-point-resolver> <include-entry-point method="getUser" /> </method-entry-point-resolver> <spring-object bean="userDao"></spring-object> </component> </service> </model>
mule中关于component的xsd很不友好, component的子项居然是一个序列, 次序不能颠倒.
现在的任务就是完成userDao 的构建.
首先给出dao的接口:
public interface Dao { public Object save(String sqlId, Object parameterObject); public int delete(String sqlId, Object parameterObject); public int update(String sqlId, Object parameterObject); public List query(String sqlId, Object parameterObject); public Object queryObject(String sqlId, Object parameterObject); public Connection getConn(); }
userDao如下:
public interface UserDao extends Dao { public List getUsers(); public User getUser(Long userId); public void saveUser(User user); public void removeUser(Long userId); }
userDao的ibatis实现:
public class UserDaoiBatis extends BaseDao implements UserDao { private DataFieldMaxValueIncrementer incrementer; public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { this.incrementer = incrementer; } public List getUsers() { return getSqlMapClientTemplate().queryForList("getUsers", null); } public User getUser(Long id) { User user = (User) getSqlMapClientTemplate().queryForObject("getUser", id); if (user == null) { throw new ObjectRetrievalFailureException(User.class, id); } return user; } public void saveUser(User user) { if (user.getId() == null) { Long id = new Long(incrementer.nextLongValue()); user.setId(id); // To use iBatis's <selectKey> feature, which is db-specific, comment // out the above two lines and use the line below instead // Long id = (Long) getSqlMapClientTemplate().insert("addUser", user); getSqlMapClientTemplate().insert("addUser", user); logger.info("new User id set to: " + id); } else { getSqlMapClientTemplate().update("updateUser", user); } } public void removeUser(Long id) { getSqlMapClientTemplate().update("deleteUser", id); } }
在spring配置文件中, 装配userDao:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxActive" value="30"/> <property name="maxIdle" value="10"/> <property name="maxWait" value="1000"/> <property name="defaultAutoCommit" value="true"/> </bean> <!-- Transaction manager for iBATIS DAOs --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- SqlMap setup for iBATIS Database Layer --> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:/co/iplatform/dao/sql-map-config.xml"/> </bean> <bean id="userIncrementer" class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer"> <property name="dataSource" ref="dataSource"/> <property name="incrementerName" value="user_sequence"/> <property name="columnName" value="value"/> </bean> <bean id="userDao" class="co.iplatform.dao.UserDaoiBatis"> <property name="incrementer" ref="userIncrementer"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <!-- Add additional DAO definitions here --> </beans>
ibatis的配置文件长大很标准,就不贴了。
写一个userDao的测试, 以确保dao正常工作:
public abstract class BaseDaoTestCase extends AbstractTransactionalDataSourceSpringContextTests { protected final Log log = logger; private ApplicationContext ctx; protected String[] getConfigLocations() { setAutowireMode(AUTOWIRE_BY_NAME); String[] paths = {"classpath*: applicationContext*.xml" }; return paths; } }
public class UserDaoTest extends BaseDaoTestCase { private User user = null; private UserDao dao = null; public void setUserDao(UserDao userDao) { this.dao = userDao; } public void testGetUsers() { user = new User(); user.setFirstName("li"); user.setLastName("chunlei"); dao.saveUser(user); System.out.println("size--"+dao.getUsers().size()); assertTrue(dao.getUsers().size() >= 1); } public void testSaveUser() throws Exception { user = new User(); user.setFirstName("li"); user.setLastName("chunlei"); dao.saveUser(user); assertTrue("primary key assigned", user.getId() != null); assertNotNull(user.getFirstName()); } public void testAddAndRemoveUser() throws Exception { user = new User(); user.setFirstName("feng"); user.setLastName("Joy"); dao.saveUser(user); assertNotNull(user.getId()); assertTrue(user.getFirstName().equals("feng")); log.debug("removing user..."); dao.removeUser(user.getId()); endTransaction(); try { user = dao.getUser(user.getId()); fail("User found in database"); } catch (DataAccessException dae) { log.debug("Expected exception: " + dae.getMessage()); assertNotNull(dae); } } }
一路绿灯.
最后,进行mule测试:
public class MyMuleClientTest { public static void main(String[] args) throws MuleException { // create mule MuleContext muleContext; String config = "mule-database-config.xml"; muleContext = new DefaultMuleContextFactory().createMuleContext(config); muleContext.start(); // creat mule client MuleClient client = new MuleClient(); MuleMessage response = client.send("vm://query", new Long(11), null); System.out.println("response = " + response.getPayload()); } }