Spring 配置
application.xml
?
?
<bean id="propertyConfigurer" destroy-method="close"><!-- Connection Info --> <property name="driverClassName"> <value>${jdbc.read.driverClassName}</value> </property> <property name="url"> <value>${jdbc.read.url}</value> </property> <property name="username"> <value>${jdbc.read.username}</value> </property> <property name="password"> <value>${jdbc.read.password}</value> </property><!-- Connection Pooling DBCP --><!-- 初始化时创建的连接数 --> <property name="initialSize" value="5" /><!-- 最大连接数据库连接数,设置为0时,表示没有限制; --> <property name="maxActive" value="100" /><!-- 最大等待连接中的数量,设置为0时,表示没有限制; --> <property name="maxIdle" value="30" /><!-- 最大等待秒数,单位为毫秒, 超过时间会报出错误信息; --> <property name="maxWait" value="100000" /><!-- 是否可用预执行 --> <property name="poolPreparedStatements" value="true" /><!-- 设置从数据源中返回的连接是否采用自动提交机制,默认值为 true;false支持事务 --> <property name="defaultAutoCommit" value="false" /><!-- 连接关闭时是否要清除缓存 --> <property name="removeAbandoned" value="true"/><!-- 清空等待时间 --> <property name="removeAbandonedTimeout" value="1"/> </bean> <context:annotation-config /> <context:component-scan base-package="com.woyo.travel.hotel"/> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-ref="writeDataSource"/> </bean>
?
读写MAP:
?
<bean id="sqlMapClientRead" name="code"><?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> <settings useStatementNamespaces="false" enhancementEnabled="true" lazyLoadingEnabled="true"/> <typeHandler jdbcType="DATE" javaType="java.util.Date" callback="com.ibatis.sqlmap.engine.type.DateTypeHandler" /> <!-- system user --><sqlMap resource="conf/sqlmap/userdefine/sqlmap-user.xml"/><sqlMap resource="conf/sqlmap/userdefine/sqlmap-category.xml"/></sqlMapConfig>?
SQLMAP:
?
<?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="activityProduct"> <resultMap id="activityProduct"> <result property="id" column="id" /> <result property="activityType" column="activity_type" /> <result property="productId" column="product_id" /> <result property="activityId" column="activity_id" /> </resultMap> <sql id="activityProduct_masterStatement"> <![CDATA[SELECT * FROM activity_product ]]> </sql> <update id="activityProduct_updateByMap" parametername="code"><context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:spring/*.xml</param-value></context-param><context-param><param-name>log4jConfigLocation</param-name><param-value>classpath:log4j.properties</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
?
?
读写分离的 Java BaseDao 类:?
?
/** * DAO基类。针对数据库的读、写操作分别采用不同的Template,可以在一定程度上防止大量并发造成的死锁。 * * @author CrayHu(hukl424@163.com) * @version Revision: 1.00 Date: 2010-6-13 */public class BaseDaoImpl<T extends DomainObject> {/** * 分页statement后缀:_count */protected static final String COUNT_STATEMENT_SUFFIX = "_count";private String entityClass;/** * 用于写操作的Template */private SqlMapClientTemplate writeTemplate;/** * 用于读操作的Template */private SqlMapClientTemplate readTemplate;/** * @return the writeTemplate */public SqlMapClientTemplate getWriteTemplate() {return writeTemplate;}/** * 需要在配置文件中配置id为writeSqlMapClient的bean * * @param sqlMapClient the SqlMapClient object to set */@Resource(name="writeSqlMapClient")public void setWriteSqlMapClient(SqlMapClient sqlMapClient) {writeTemplate = new SqlMapClientTemplate(sqlMapClient);}/** * @return the readTemplate */public SqlMapClientTemplate getReadTemplate() {return readTemplate;}/** * 需要在配置文件中配置id为writeSqlMapClient的bean * * @param sqlMapClient the SqlMapClient object to set */@Resource(name="readSqlMapClient")public void setReadSqlMapClient(SqlMapClient sqlMapClient) {readTemplate = new SqlMapClientTemplate(sqlMapClient);}/** * 新增实体类 * * @param statement * @param entity * @return */protected DomainObject save(String statement, DomainObject entity) {Integer entityId = (Integer)writeTemplate.insert(statement, entity);if(entityId != null && entityId > 0) {entity.setId(entityId);}return entity;}/** * 新增 * * @param statement * @param entity */protected void save(String statement, Object entity) {writeTemplate.insert(statement, entity);}/** * 新增返回本次会话自增Id。 * added by wallce_xu * * @param statement * @param entity */protected int savegetId(String statement, Object entity) {return (Integer)(writeTemplate.insert(statement, entity));}/** * 新增返回本次会话自增id * added by wallce_xu * * @param statement * @param entity */protected void saveid(String statement, Object entity) {int i = (Integer) writeTemplate.insert(statement, entity);}/** * 修改 * * @param statement * @param params */protected void update(String statement, Object params) {writeTemplate.update(statement, params);}/** * 根据参数删除 * * @param statement * @param params */protected void delete(String statement, Object params) {writeTemplate.delete(statement, params);}/** * 批量删除 * @param statement * @param params */protected void deleteByIds(String statement, Object params) {writeTemplate.delete(statement, params);}/** * 根据参数取得<code>T</code>类型实体 * * @param statement * @param params * @return */@SuppressWarnings("unchecked")protected T getEntity(String statement, Object params) {return (T)readTemplate.queryForObject(statement, params);}/** * 根据根据参数取得任意类型实体 * * @param statement * @param param * @return */protected Object getObject(String statement, Object param) {return readTemplate.queryForObject(statement, param);}/** * 根据参数查询列表,可分页 * * @param statement * @param params * @return */@SuppressWarnings("unchecked")protected List<T> query(String statement, QueryParams params) {if(params != null && params.getPaging() != null) {int records = queryCount(statement, params);//如果查询出符合条件的记录数为0,那么就直接返回一个空的List,因为后面的已经没有执行的必要if(records == 0) {return new ArrayList<T>(0);}params.getPaging().setRecords(records);}return (List<T>)readTemplate.queryForList(statement, params);}/** * 根据参数查询列表,可分页 * * @param statement * @param params * @return */@SuppressWarnings("unchecked")protected List queryEntities(String statement, QueryParams params) {if(params != null && params.getPaging() != null) {int records = queryCount(statement, params);//如果查询出符合条件的记录数为0,那么就直接返回一个空的List,因为后面的已经没有执行的必要if(records == 0) {return new ArrayList<T>(0);}params.getPaging().setRecords(records);}return readTemplate.queryForList(statement, params);}/** * 查询列表,不提供分页功能 * * @param statement * @param params * @return */@SuppressWarnings("unchecked")protected List<T> query(String statement, Object params) {return (List<T>)readTemplate.queryForList(statement, params);}/** * 无参数查询列表,不提供分页功能 * * @param statement * @return */@SuppressWarnings("unchecked")protected List<T> query(String statement) {return (List<T>)readTemplate.queryForList(statement);}/** * 查询任意类型的对象列表。不局限于T类型的 * * @param statement * @param params * @return */@SuppressWarnings("unchecked")protected List queryEntities(String statement, Object params) {return readTemplate.queryForList(statement, params);}/** * 批量新增/修改/删除。注意批量新增时是无法正确的获取自增主键的值(批处理中最后一个新增可以获取正确的值,其它皆不可以), * 所以如果需要获取自增主键的值,不应该使用该方法。 * * @param statement * @param params * @return 返回操作影响的行数 */protected int batch(final String statement, final Object[] params) {return (Integer)writeTemplate.execute(new SqlMapClientCallback() {@Overridepublic Object doInSqlMapClient(SqlMapExecutor executor)throws SQLException {executor.startBatch();for(Object param : params) {if(param == null) {continue;}executor.update(statement, param);}return executor.executeBatch();}});}/** * 根据参数判断该记录是否已存在(逻辑上存在) * * @param statement * @param params * @return */protected boolean isExistEntity(String statement, Object params) {return (Integer)readTemplate.queryForObject(statement, params) > 0;}/** * 取得指定的statement的完全限定名称。形式为<code>namespace</code> + "." + <code>statement</code> * * @param namespace * @param statement * @return */protected String getQualifiedName(String namespace, String statement) {return new StringBuffer().append(namespace).append(".").append(statement).toString();}/** * 取得指定的statement的完全限定名称。该方法以泛型<code>T</code>的实际类型的完全限定名 + "." + <code>statement</code>。这就要求在 * 书写iBatis配置文件时,namespace必须写成“泛型<code>T</code>的实际类型的完全限定名”。<br> * 例如,如果有DAO实现类TravelGuideDaoImpl<TravelGuide>,TravelGuide位于com.woyoframework.travel.core.bo.guide下, * 那么调用该方法将返回com.woyoframework.travel.core.bo.guide.TravelGuide.xxx。 * * @param statement * @return */@SuppressWarnings("unchecked")protected String getQualifiedName(String statement) {/** * 避免每次都去获取 */if(StringUtils.isBlank(entityClass)) {entityClass = DomainObject.class.getName();Type superClass = getClass().getGenericSuperclass();if(superClass instanceof ParameterizedType) {ParameterizedType genericType = (ParameterizedType)superClass;Type[] typeArgs = genericType.getActualTypeArguments();if(typeArgs.length > 0) {entityClass = ((Class<T>)typeArgs[0]).getName();}}}return new StringBuffer().append(entityClass).append(".").append(statement).toString();}/** * 根据条件查询整数结果。 * * @param statement * @param params * @return */protected int uniqueIntResult(String statement, Object params) {if(params == null) {return (Integer)readTemplate.queryForObject(statement);}Object result = (Integer)readTemplate.queryForObject(statement, params);return result != null ? (Integer)result : 0;}/** * 查询符合条件的记录数,仅供分页查询调用。 * * @param statement * @param params * @return * update andy_luo 2010-7-2 15:43 增加params非空判断,如果为空表示查询所有的数量 */protected int queryCount(String statement,QueryParams<?> params) {if(params == null) {return (Integer)readTemplate.queryForObject(statement + COUNT_STATEMENT_SUFFIX);}return (Integer)readTemplate.queryForObject(statement + COUNT_STATEMENT_SUFFIX, params);}}?
?
?
1 楼 chenhuilove123 2011-06-17 牛B.............