1.jdbc.properties
#Apache-dbcp\u6570\u636e\u6e90\u914d\u7f6e
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=kaifahyip
jdbc.password=123456
jdbc.url=jdbc:mysql://192.168.7.154:3306/tickets?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&autoReconnectForPools=true
jdbc.reader.username=kaifahyip
jdbc.reader.password=123456
jdbc.reader.url=jdbc:mysql://192.168.7.154:3306/tickets?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&autoReconnectForPools=true
#jdbc.username=apps
#jdbc.password=123456
#jdbc.url=jdbc:mysql://127.0.0.1:3306/tickets
#\u8fde\u63a5\u6c60\u542f\u52a8\u65f6\u7684\u521d\u59cb\u503c
jdbc.initialSize=50
#\u8fde\u63a5\u6c60\u7684\u6700\u5927\u503c
jdbc.maxActive=500
#\u6700\u5927\u7a7a\u95f2\u503c,\u5982\u679c\u8fd9\u4e2a\u53c2\u6570\u7684\u503c\u6bd4maxActive\u4f4e,\u5728\u9ad8\u8d1f\u8f7d\u7684\u60c5\u51b5\u4e0b\u5c31\u4f1a\u4ea7\u751f\u5f88\u591atime_waited\u7ebf\u7a0b,\u6839\u636e\u6211\u4eec\u7684\u6d4b\u8bd5\u7ed3\u679c,\u8fd9\u4e2a\u503c\u6700\u597d\u548cmaxActive\u76f8\u540c\u6216\u8005\u662f\u8bbe\u6210-1
jdbc.maxIdle=100
#\u6700\u5c0f\u7a7a\u95f2\u503c
jdbc.minIdle=50
#\u8d85\u65f6\u7b49\u5f85\u65f6\u95f4\u4ee5\u6beb\u79d2\u4e3a\u5355\u4f4d
jdbc.maxWait=30000
#touch mysql\u6570\u636e\u5e93\u7684wait_timeout\u8bbe\u7f6e
jdbc.validationQuery=select 1
#\u8fde\u63a5\u653e\u56de\u6c60\u4e2d\u65f6\u53d1\u9001validationQuery
jdbc.testOnReturn=true
#\u6807\u8bb0\u662f\u5426\u5220\u9664\u6cc4\u9732\u7684\u8fde\u63a5,\u5982\u679c\u4ed6\u4eec\u8d85\u8fc7\u4e86removeAbandonedTimout\u7684\u9650\u5236
jdbc.removeAbandoned=true
#\u6cc4\u9732\u7684\u8fde\u63a5\u53ef\u4ee5\u88ab\u5220\u9664\u7684\u8d85\u65f6\u503c(\u5355\u4f4d\u79d2),\u5982\u679c\u8bbe\u7f6e\u4e86removeAbandoned\u4e3atrue
jdbc.removeAbandonedTimeout=10
#\u4e8b\u52a1\u81ea\u52a8\u63d0\u4ea4
jdbc.defaultAutoCommit=false
2.applicationContext-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- 后台管理系统数据源配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="url" value="${jdbc.url}"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${jdbc.initialSize}"/>
<!-- 连接池的最大值,最好和maxActive相同或者是设成-1 -->
<property name="maxActive" value="${jdbc.maxActive}"/>
<!-- 最大空闲值 -->
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<!-- 最小空闲值 -->
<property name="minIdle" value="${jdbc.minIdle}"/>
<!-- 超时等待时间以毫秒为单位 -->
<property name="maxWait" value="${jdbc.maxWait}"/>
<!-- touch mysql数据库的wait_timeout设置 -->
<property name="validationQuery" value="${jdbc.validationQuery}"/>
<!-- 连接放回池中时发送validationQuery -->
<property name="testOnReturn" value="${jdbc.testOnReturn}"/>
<!-- 标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制 -->
<property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>
<!-- 泄露的连接可以被删除的超时值(单位秒),如果设置了removeAbandoned为true -->
<property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>
<!-- 开启MySQL batch模式 -->
<property name="connectionProperties" value="rewriteBatchedStatements=true"/>
</bean>
<bean id="dataSource4Reader" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.reader.username}"/>
<property name="password" value="${jdbc.reader.password}"/>
<property name="url" value="${jdbc.reader.url}"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${jdbc.initialSize}"/>
<!-- 连接池的最大值,最好和maxActive相同或者是设成-1 -->
<property name="maxActive" value="${jdbc.maxActive}"/>
<!-- 最大空闲值 -->
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<!-- 最小空闲值 -->
<property name="minIdle" value="${jdbc.minIdle}"/>
<!-- 超时等待时间以毫秒为单位 -->
<property name="maxWait" value="${jdbc.maxWait}"/>
<!-- touch mysql数据库的wait_timeout设置 -->
<property name="validationQuery" value="${jdbc.validationQuery}"/>
<!-- 连接放回池中时发送validationQuery -->
<property name="testOnReturn" value="${jdbc.testOnReturn}"/>
<!-- 标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制 -->
<property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>
<!-- 泄露的连接可以被删除的超时值(单位秒),如果设置了removeAbandoned为true -->
<property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>
<!-- 开启MySQL batch模式 -->
<property name="connectionProperties" value="rewriteBatchedStatements=true"/>
</bean>
<!-- jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="jdbcTransactionManager" proxy-target-class="true"/>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory4Reader" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/>
<property name="dataSource" ref="dataSource4Reader"/>
</bean>
<bean id="defaultSqlSessionTemplate" class="com.common.mybatis.DelegateSqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
<constructor-arg index="1" value="SIMPLE"/>
</bean>
<bean id="sqlSessionTemplate4Reader" class="com.common.mybatis.DelegateSqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory4Reader"/>
<constructor-arg index="1" value="SIMPLE"/>
</bean>
<bean id="batchSqlSessionTemplate" class="com.common.mybatis.DelegateSqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
<constructor-arg index="1" value="BATCH"/>
</bean>
</beans>
3.DelegateSqlSessionTemplate.java
package com.common.mybatis;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import com.common.util.EscapeFilter;
import com.common.util.Pager;
import com.common.util.PaginationUtils;
/**
* 该类是{@link #SqlSessionTemplate}的代理类,增加了几个便于开发的方法,如分页查询方法
*
*
* @date 2014年6月18日 下午6:26:20
* @version 1.0
*/
public class DelegateSqlSessionTemplate implements SqlSession {
/**
* 默认分页总数查询statementKey的后缀
* 例如分页查询数据的statementKey为'getXxxxList',则针对该分页的查询总记录数的statementKey一定要以<code>DEFAULT_PAGING_COUNT_STATEMENT_KEY_SUFFIX</code>结尾,例如:
* <p/>
* <select id="selectMyOrderList" parameterType="java.util.Map" statementType="PREPARED" resultType="OrderInfo">
* select * from t_order_info a where a.user_id = #{userId}
* </select>
* 其分页count的查询statementKey的定义应如下:
* <select id="selectMyOrderList_count" parameterType="java.util.Map" statementType="PREPARED" resultType="Integer">
* select count(*) from t_order_info a where a.user_id = #{userId}
* </select>
*/
public static final String DEFAULT_PAGING_COUNT_STATEMENT_KEY_SUFFIX = "_count";
private SqlSession delegate;
public DelegateSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
delegate = new SqlSessionTemplate(sqlSessionFactory);
}
public DelegateSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
delegate = new SqlSessionTemplate(sqlSessionFactory, executorType);
}
public void clearCache() {
delegate.clearCache();
}
public void close() {
delegate.close();
}
public void commit() {
delegate.commit();
}
public void commit(boolean force) {
delegate.commit(force);
}
public int delete(String statement) {
return delegate.delete(statement);
}
public int delete(String statement, Object parameter) {
return delegate.delete(statement, parameter);
}
public List<BatchResult> flushStatements() {
return delegate.flushStatements();
}
public Configuration getConfiguration() {
return delegate.getConfiguration();
}
public Connection getConnection() {
return delegate.getConnection();
}
public <T> T getMapper(Class<T> type) {
return delegate.getMapper(type);
}
public int insert(String statement) {
return delegate.insert(statement);
}
public int insert(String statement, Object parameter) {
return delegate.insert(statement, parameter);
}
public void rollback() {
delegate.rollback();
}
public void rollback(boolean force) {
delegate.rollback(force);
}
public void select(String statement, ResultHandler handler) {
delegate.select(statement, handler);
}
public void select(String statement, Object parameter, ResultHandler handler) {
delegate.select(statement, parameter, handler);
}
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
delegate.select(statement, parameter, rowBounds, handler);
}
public <E> List<E> selectList(String statement) {
return delegate.selectList(statement);
}
public <E> List<E> selectList(String statement, Object parameter) {
return delegate.selectList(statement, parameter);
}
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return delegate.selectList(statement, parameter, rowBounds);
}
public <K, V> Map<K, V> selectMap(String statement, String parameter) {
return delegate.selectMap(statement, parameter);
}
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return delegate.selectMap(statement, parameter, mapKey);
}
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
return delegate.selectMap(statement, parameter, mapKey, rowBounds);
}
public <T> T selectOne(String statement) {
return delegate.selectOne(statement);
}
public <T> T selectOne(String statement, Object parameter) {
return delegate.selectOne(statement, parameter);
}
public int update(String statement) {
return delegate.update(statement);
}
public int update(String statement, Object parameter) {
return delegate.update(statement, parameter);
}
/**
* EscapeFilter的作用:对key-value键值对型数据转换,例如:
* <p/>
* return orderInfoDAO.selectOne(MybatisUtils.getMapperKey(OrderInfo.class, "selectOrderInfoById"), orderId, new EscapeFilter<OrderInfo>() {
* public void doEscapeFilter(OrderInfo element) {
* element.setOrderTypeName(OrderTypeEnum.getTypeName(element.getOrderType()));
* ...
* ...
* }
* });
*
* @param statementKey
* @param paramObj
* @param escapeFilter
* @return
*/
public <T> T selectOne(String statementKey, Object paramObj, EscapeFilter<T> escapeFilter) {
EscapeResultHandler<T> resultHandler = new EscapeResultHandler<T>(escapeFilter);
delegate.select(statementKey, paramObj, resultHandler);
List<T> list = resultHandler.getResultList();
if (list == null || list.isEmpty()) {
return null;
} else if (list.size() == 1) {
return list.get(0);
}
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
}
/**
* EscapeFilter的作用:对key-value键值对型数据转换,例如:
* <p/>
* return orderInfoDAO.selectOne(MybatisUtils.getMapperKey(OrderInfo.class, "selectOrderInfoById"), orderId, new EscapeFilter<OrderInfo>() {
* public void doEscapeFilter(OrderInfo element) {
* element.setOrderTypeName(OrderTypeEnum.getTypeName(element.getOrderType()));
* ...
* ...
* }
* });
*
* @param statementKey
* @param paramObj
* @param escapeFilter
* @return
*/
public <T> List<T> selectList(String statementKey, Object paramObj, EscapeFilter<T> escapeFilter) {
EscapeResultHandler<T> resultHandler = new EscapeResultHandler<T>(escapeFilter);
delegate.select(statementKey, paramObj, resultHandler);
return resultHandler.getResultList();
}
/**
* 带分页的查询
*
* @param statementKey
* @param paramObj
* @param pager
* @return
*/
public <T> List<T> selectList(String statementKey, Object paramObj, Pager pager) {
Integer totalRowCount = delegate.selectOne(statementKey + DEFAULT_PAGING_COUNT_STATEMENT_KEY_SUFFIX, paramObj);
pager.setTotalNum(totalRowCount);
PaginationUtils.setPageItems(pager);
if(totalRowCount > 0){
int offset = (pager.getPageIndex() - 1) * pager.getPageNum();
return delegate.selectList(statementKey, paramObj, new RowBounds(offset, pager.getPageNum()));
}
return new ArrayList<T>(0);
}
/**
* 带分页的查询
*
* @param statementKey
* @param paramObj
* @param escapeFilter
* @param pager
* @return
*/
public <T> List<T> selectList(String statementKey, Object paramObj, EscapeFilter<T> escapeFilter, Pager pager) {
Integer totalRowCount = delegate.selectOne(statementKey + DEFAULT_PAGING_COUNT_STATEMENT_KEY_SUFFIX, paramObj);
pager.setTotalNum(totalRowCount);
PaginationUtils.setPageItems(pager);
if(totalRowCount > 0){
int offset = (pager.getPageIndex() - 1) * pager.getPageNum();
EscapeResultHandler<T> resultHandler = new EscapeResultHandler<T>(escapeFilter);
delegate.select(statementKey, paramObj, new RowBounds(offset, pager.getPageNum()), resultHandler);
return resultHandler.getResultList();
}
return new ArrayList<T>(0);
}
}
4.util类
package com.common.util;
import java.util.List;
/**
* 通用分页类
*
* @version 1.0
* @date 2014年6月13日 上午8:59:16
*/
public class Pager {
/**
* 第几页
*/
private Integer pageIndex = 1;
/**
* 每页显示多少条
*/
private Integer pageNum = 10;
/**
* 总记录条数
*/
private Integer totalNum = 0;
private Integer totalPage;
/**
* 分页页码列表
* 例如:
* [1,2,3,4,5,null,10] 其中null代表省略号...
*/
private List<Integer> pageItems;
private int pageMargin = 2;
public Pager() {
super();
}
public Pager(Integer pageIndex, Integer pageNum) {
super();
setPageIndex(pageIndex);
setPageNum(pageNum);
}
public Integer getPageIndex() {
return pageIndex;
}
public void setPageIndex(Integer pageIndex) {
this.pageIndex = pageIndex;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getTotalNum() {
return totalNum;
}
public void setTotalNum(Integer totalNum) {
this.totalNum = totalNum == null ? 0 : totalNum;
if (this.totalNum > 0) {
this.totalPage = this.totalNum % this.pageNum == 0 ? (this.totalNum / this.pageNum) : ((this.totalNum / this.pageNum) + 1);
} else {
this.totalPage = 0;
}
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<Integer> getPageItems() {
return pageItems;
}
public void setPageItems(List<Integer> pageItems) {
this.pageItems = pageItems;
}
public int getPageMargin() {
return pageMargin;
}
public void setPageMargin(int pageMargin) {
this.pageMargin = pageMargin;
}
public static Pager all(){
Pager all = new Pager();
all.setPageIndex(1);
all.setPageNum(Integer.MAX_VALUE);
return all;
}
public boolean isAll(){
return this.getPageNum() == Integer.MAX_VALUE;
}
}
package com.common.util;
import java.util.ArrayList;
import java.util.List;
/**
* 分页页码生成工具类
*
*
* @date 2013-10-28 上午11:03:09
* @version 1.0
*/
public class PaginationUtils {
/**
* 生成分页页码
* @param pageMargin - 当前页的前后margin, 例如currentPage = 5,pageMargin = 2,则3,4,5,6,7这个五个页码是必须显示的
* @param currentPage - 当前页码
* @param totalPageCount - 总页数
* @return
*/
public static List<Integer> getPaginationItems(int pageMargin, int currentPage, int totalPageCount) {
List<Integer> pageItems = new ArrayList<Integer>();
if(pageMargin < 1){
throw new IllegalArgumentException("'pageMargin' can not less than 1!");
}
if(currentPage < 1){
throw new IllegalArgumentException("'currentPage' can not less than 1!");
}
if(totalPageCount < 0){
throw new IllegalArgumentException("'totalPageCount' can not less than 0!");
}
if(totalPageCount < currentPage){
return pageItems;
}
int start = currentPage - pageMargin;
int end = currentPage + pageMargin;
if(start <= 0){
int offset = Math.abs(start) + 1;
start = start + offset;
end = end + offset;
}
if(end > totalPageCount){
int offset = totalPageCount - end;
end = end + offset;
start = start + offset;
start = start < 1 ? 1 : start;
}
for(int i = start; i <= end; i++){
if(i == start && i > 1){ //first
pageItems.add(1);
if(i - 1 > 2){
pageItems.add(null);
}else if(i - 1 == 2){
pageItems.add(i - 1);
}
}
pageItems.add(i);
if(i == end && i < totalPageCount){ //last
if(totalPageCount - end > 2){
pageItems.add(null);
}else if(totalPageCount - end == 2){
pageItems.add(totalPageCount - 1);
}
pageItems.add(totalPageCount);
}
}
return pageItems;
}
public static void setPageItems(Pager pager) {
pager.setPageItems(getPaginationItems(pager.getPageMargin(), pager.getPageIndex(), pager.getTotalPage()));
}
}
package com.common.util;
/**
* 针对对象的某个属性的"值"与"义"的转义接口,如
* public class User {
* private String userType;
* <p/>
* private String userTypeName;
* }
* 对于从数据库中查出来的User对象可能仅仅是userType=0,1,2这样的代码所表示的常量值,
* 而用于展示在页面上的字段userTypeName却是没有赋值,
* 该EscapeFilter接口即为解决此类情况下的"值"与"义"的转换功能的
*
* @param <T>
*
* @version 1.0
* @date 2013-10-14 下午9:47:16
*/
public interface EscapeFilter<T> {
public void doEscapeFilter(T element);
}
public static class FilmEscapeFilter implements EscapeFilter<Film> {
public void doEscapeFilter(Film element) {
try {
element.setScreenTypeName(FilmScreenTypeEnum.getTypeName(Integer.valueOf(element.getScreenType())));
element.setBindStatusName(FilmBindStatusEnum.getStatusName(element.getBindStatus()));
element.setFullPosterPath(CommonConstants.IMG_DOMAIN + element.getPosterPath());
element.setPosterPath1(FilmPhotoUtils.getDimensionStyleFileName(element.getPosterPath(), FilmPosterPhotoUploadConfig.DIMENSION_400x600));
element.setPosterPath2(FilmPhotoUtils.getDimensionStyleFileName(element.getPosterPath(), FilmPosterPhotoUploadConfig.DIMENSION_280x420));
element.setFullPosterPath1(FilmPhotoUtils.getDimensionStyleFileName(element.getFullPosterPath(), FilmPosterPhotoUploadConfig.DIMENSION_400x600));
element.setFullPosterPath2(FilmPhotoUtils.getDimensionStyleFileName(element.getFullPosterPath(), FilmPosterPhotoUploadConfig.DIMENSION_280x420));
} catch (Exception e) {}
}
}
5.BaseMybatisDAO.java
package com.common.dao.base;
import javax.annotation.Resource;
import com.common.mybatis.DelegateSqlSessionTemplate;
import com.common.util.MybatisUtils;
/**
* 基于Mybatis的DAO基类
*
* @version 1.0
* @date 2014年6月13日 下午10:30:46
*/
public abstract class BaseMybatisDAO {
@Resource(name="defaultSqlSessionTemplate")
private DelegateSqlSessionTemplate sqlSessionTemplate;
@Resource(name = "sqlSessionTemplate4Reader")
private DelegateSqlSessionTemplate sqlSessionTemplate4Reader;
public DelegateSqlSessionTemplate getSqlSessionTemplate() {
return sqlSessionTemplate;
}
public DelegateSqlSessionTemplate getSqlSessionTemplate4Reader() {
return sqlSessionTemplate4Reader;
}
protected String getMapperKey(Class<?> mapperClass, String key) {
return MybatisUtils.getMapperKey(mapperClass, key);
}
}
6.Dao
@Repository("billDAO")
public class BillDAOImpl extends BaseMybatisDAO implements BillDAO {
@Override
public Integer getUserBindNum(Long billId, Long userId) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("billId", billId);
paramMap.put("userId", userId);
return getSqlSessionTemplate4Reader().selectOne(getMapperKey("getUserBindNum"), paramMap);
}
@Override
public Integer binding(Long billCodeId, Long userId, String userName) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("billCodeId", billCodeId);
paramMap.put("userId", userId);
paramMap.put("userName", userName);
paramMap.put("bindingTime", DateTime.now().toString(DateTimeUtils.DEFAULT_DATE_FORMAT_PATTERN_FULL));
return getSqlSessionTemplate().update(getMapperKey("binding"), paramMap);
}
}