数据源配置
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- spring的属性加载器,加载properties文件中的属性 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:common.properties</value>
</property>
<property name="fileEncoding" value="utf-8" />
</bean>
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="jdbcUrl">
<value>jdbc:mysql://${mysql.db.ip}:${mysql.db.port}/${mysql.db.database}?useUnicode=true&characterEncoding=UTF-8</value>
</property>
<property name="user">
<value>${mysql.db.user}</value>
</property>
<property name="password">
<value>${mysql.db.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>1</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>15</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>1</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>5</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
</bean>
<!-- 连接管理对象 -->
<bean id="c3P0ConnectionProvider"
class="com.kingdee.mysql.provider.C3P0ConnectionProvider">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
数据源生成器代码
package com.kingdee.mysql.provider;
import java.sql.Connection;
public interface ConnecttionProvider {
public Connection getConnection()throws Exception;
}
package com.kingdee.mysql.provider;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Component;
@Component
public class C3P0ConnectionProvider implements ConnecttionProvider{
@Autowired
private DataSource dataSource;
public Connection getConnection() throws Exception {
// TODO Auto-generated method stub
Connection connection = dataSource.getConnection();
return connection;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource){
if(dataSource == null){
System.out.println("===null====");
}else {
System.out.println("======!!!!null");
}
this.dataSource = dataSource;
}
}
package com.kingdee.dao.impl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import org.hibernate.validator.internal.util.privilegedactions.GetMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import com.kingdee.dao.IPage;
import com.kingdee.dao.JdbcUtil;
import com.kingdee.mysql.provider.ConnecttionProvider;
import com.mysql.cj.jdbc.result.ResultSetMetaData;
import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.List;
public class CommonDao {
private static Logger logger = LoggerFactory.getLogger(CommonDao.class);
@Autowired
private ConnecttionProvider c3P0ConnectionProvider;
public ConnecttionProvider getC3P0ConnectionProvider() {
return c3P0ConnectionProvider;
}
public void setC3P0ConnectionProvider(ConnecttionProvider c3p0ConnectionProvider) {
c3P0ConnectionProvider = c3p0ConnectionProvider;
}
public IPage getPage() {
return page;
}
public void setPage(IPage page) {
this.page = page;
}
private static ThreadLocal<Connection> connWrapper = new ThreadLocal<Connection>();
@Autowired
private IPage page;
public Connection getConnection() throws Exception {
Connection connection = connWrapper.get();
if (connection != null && !connection.isClosed()) {
return connection;
}
// 取连接并放入线程属性域中
connection = c3P0ConnectionProvider.getConnection();
if (connection == null) {
throw new SQLException("无法获取数据库连接");
}
connWrapper.set(connection);
return connection;
}
// 如果当前线程有连接则调用该方法关闭掉
public static void closeConnection() {
Connection conn = connWrapper.get();
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
logger.error("Can not close database connection", e);
}
// 释放掉保存的对象
connWrapper.remove();
}
}
public Method getMethod(Method[] methods,String pre, String name){
for(Method method:methods){
String methodname = method.getName();
if (methodname.equalsIgnoreCase(pre+name)) {
return method;
}
}
return null;
}
public void cleanup(ResultSet set,PreparedStatement pre){
if (set!=null) {
try{
set.close();
}catch(SQLException e){
}
}
cleanup(pre);
}
public void cleanup(PreparedStatement pre){
if (pre!=null) {
try{
pre.close();
}catch(SQLException e){
}
}
}
public void cleanup(Statement stat) {
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
// ignore
}
}
}
public <T> LinkedList<T> queryBeans(String sql, Object[] params, Class<T> clazz, int offset, int limit) throws Exception{
Connection con = getConnection();
LinkedList<T> result = new LinkedList<T>();
sql = page.formatPageSQL(sql, offset, limit);
ResultSet rs = null;
PreparedStatement pre = null;
try{
pre = con.prepareStatement(sql);
if(params!=null&¶ms.length>0){
for(int i=0;i<params.length;i++){
pre.setObject(i+1, params[i]);
}
}
rs = pre.executeQuery();
ResultSetMetaData RSMD = (ResultSetMetaData) rs.getMetaData();
int count = RSMD.getColumnCount();
Method[] methods = clazz.getMethods();
while(rs.next()){
T bean = clazz.newInstance();
for(int i=1;i<=count;i++){
String name = RSMD.getColumnName(i);
Method method = getMethod(methods,"set",name);
if (method==null) {
continue;
}
Class[] arguments = method.getParameterTypes();
Object value = JdbcUtil.getResultSetValue(rs, i, arguments[0]);
method.invoke(bean, value);
}
result.add(bean);
}
}finally{
cleanup(rs, pre);
closeConnection();
}
return result;
}
public LinkedList<HashMap<String,Object>> query(String sql, Object[] params, int offset, int limit) throws Exception{
Connection con = getConnection();
sql = page.formatPageSQL(sql, offset, limit);
ResultSet rs = null;
PreparedStatement pre = null;
LinkedList<HashMap<String,Object>> result = new LinkedList<HashMap<String,Object>>();
try{
pre = con.prepareStatement(sql);
if(params!=null&¶ms.length>0){
for(int i=0;i<params.length;i++){
pre.setObject(i+1, params[i]);
}
}
rs = pre.executeQuery();
ResultSetMetaData RSMD = (ResultSetMetaData) rs.getMetaData();
int count = RSMD.getColumnCount();
while(rs.next()){
HashMap<String,Object> map = new HashMap<String,Object>();
for(int i=1;i<=count;i++){
Object value = rs.getObject(i);
String name = RSMD.getColumnName(i);
map.put(name, value);
}
result.add(map);
}
}finally{
cleanup(rs, pre);
closeConnection();
}
return result;
}
/**
* 查询单一的实体对象
*
* @param <T>
* @param sql
* @param clazz
* @return
*/
public <T> T querySingleBean(String sql, Class<T> clazz)
throws Exception {
return this.querySingleBean(sql, new Object[0], clazz);
}
public <T> T querySingleBean(String sql, Object[] params,
Class<T> clazz) throws Exception {
LinkedList<T> beans = this.queryBeans(sql, params, clazz);
if (beans == null || beans.isEmpty()) {
return null;
}
return beans.get(0);
}
public <T> T querySingleBean(String sql, Class<T> clazz,
Object... params) throws Exception {
if (params == null) {
return querySingleBean(sql, (Object[]) null, clazz);
}
return querySingleBean(sql, params, clazz);
}
/**
* 支持分页的查询
*
* @param <T>
* @param sql
* @param clazz
* @param offset
* @param limit
* @return
* @throws Exception
*/
public <T> LinkedList<T> queryBeans(String sql, Class<T> clazz,
int offset, int limit) throws Exception {
return queryBeans(sql, null, clazz, offset, limit);
}
/**
*
* @param <T>
* @param sql
* @param clazz
* @return
* @throws Exception
*/
public <T> LinkedList<T> queryBeans(String sql, Class<T> clazz)
throws Exception {
return this.queryBeans(sql, new Object[0], clazz);
}
/**
*
* @param sql
* @param params
* @return
*/
public <T> LinkedList<T> queryBeans(String sql, Object[] params,
Class<T> clazz) throws Exception {
return queryBeans(sql, params, clazz, 0, 0);
}
public <T> LinkedList<T> queryBeans(String sql, Class<T> clazz,
Object[] params) throws Exception {
return queryBeans(sql, params, clazz, 0, 0);
}
public <T> LinkedList<T> queryBeans(String sql, Class<T> clazz,
int offset, int limit, Object... params) throws Exception {
return queryBeans(sql, (Object[]) params, clazz, offset, limit);
}
/**
* 查询
*
* @param sql
* @return
*/
public LinkedList<HashMap<String, Object>> query(String sql) throws Exception {
return this.query(sql, 0,0);
}
public LinkedList<HashMap<String, Object>> query(String sql, int offset, int limit)
throws Exception {
return this.query(sql, (String[]) null, offset, limit);
}
public LinkedList<HashMap<String, Object>> query(String sql, Object[] params)
throws Exception {
return this.query(sql, params, 0,0);
}
public HashMap<String, Object> querySingle(String sql, Object[] params)
throws Exception {
LinkedList<HashMap<String, Object>> result = query(sql, params);
if (result.isEmpty()) {
return null;
}
return result.get(0);
}
/**
* @deprecated
* @param sql
* @param params
* @return
*/
public <T> int countBeans(String sql, Object[] params,
Class<T> clazz) throws Exception {
LinkedList<T> result = this.queryBeans(sql, params, clazz);
return result == null ? -1 : result.size();
}
/**
* 查询数据库中的单一整形字段
*
* @param sql
* @param params
* @return
* @throws Exception
*/
public int queryIntegerValue(String sql, Object[] params) throws Exception {
LinkedList<HashMap<String, Object>> result = this.query(sql, params);
if (result == null || result.isEmpty()) {
return -1;
}
HashMap<String, Object> data = result.get(0);
Object[] ret = data.values().toArray();
if (ret.length == 0 || ret[0] == null) {
return -1;
}
return ((Number) ret[0]).intValue();
}
public int queryIntegerValue(String sql) throws Exception {
return this.queryIntegerValue(sql, new Object[0]);
}
public int count(String sql) throws Exception {
return this.queryIntegerValue(sql, new Object[0]);
}
public int count(String sql, Object[] params) throws Exception {
return this.queryIntegerValue(sql, params);
}
/**
* 执行数据的更新操作
*
* @param sql
* @param params
* @return
* @throws Exception
*/
public int execute(String sql) throws Exception {
return this.execute(sql, new Object[0]);
}
// note:UPDATE和DELETE操作能返回被操作到的行数,INSERT成功则都是返回0
public int execute(String sql, Object[] params) throws Exception {
Connection conn = getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
return ps.executeUpdate();
} finally {
cleanup(ps);
closeConnection();
}
}
public boolean existByCondition(String tableName, String condition,
Object... params) throws Exception {
return this.count("select count(0) from " + tableName + " where "
+ condition, params) != 0;
}
/**
* 执行删除操作
*
* @param tableName
* @param conditions
* @param params
* @throws Exception
*/
public int delete(String tableName, String conditions, Object... params)
throws Exception {
StringBuffer sql = new StringBuffer("DELETE FROM ");
sql.append(tableName);
sql.append(" WHERE ");
sql.append(conditions);
return this.execute(sql.toString(), params);
}
public <T> int createBean(T bean, String tableName)
throws Exception {
return this.createBean(bean, tableName, null);
}
/**
* 在数据库中创建一个对象: 使用约定优于配置的方式 <br>
* 1.所有的get属性的字段与数据库中对应 <br>
* 2.表名与实体名对应(或者需要将表名传递进来)<br>
*
* @param <T>
* @param bean
* @return
* @throws Exception
*/
public <T> int createBean(T bean, String tableName,
LinkedList<String> ignoreFieldNames) throws Exception {
// 分析bean中的数据
Class clazz = bean.getClass();
Map<String, Object> data = new LinkedHashMap<String, Object>();
Field[] fields = clazz.getDeclaredFields();
Method[] allMethods = clazz.getMethods();
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
String name = f.getName();
if (ignoreFieldNames != null && ignoreFieldNames.contains(name)) {
continue;
}
// 忽略javabean字段的大小写
Method method = this.getMethod(allMethods,"get", name);
if (method != null) {
data.put(f.getName(), method.invoke(bean, new Object[0]));
}
}
}
// 合成insert SQL语句
StringBuffer sql = new StringBuffer("INSERT INTO " + tableName
+ data.keySet().toString().replace("[", "(").replace("]", ")")
+ " VALUES(");
LinkedList<Map.Entry<String, Object>> entrys = new LinkedList<Map.Entry<String, Object>>(
data.entrySet());
int size = entrys.size();
Object[] params = new Object[size];
for (int i = 0; i < size; i++) {
Map.Entry<String, Object> entry = entrys.get(i);
sql.append("?");
if (i != size - 1) {
sql.append(",");
}
params[i] = entry.getValue();
}
sql.append(")");
// 执行sql
return this.execute(sql.toString(), params);
}
public <T> int createBean(T bean) throws Exception {
return this.createBean(bean, bean.getClass().getSimpleName());
}
/**
*
* @param <T>
* @param bean
* @param idcol
* @param tableName
* @return
* @throws Exception
*/
private static boolean isIgnoreCols(String colName, String[] ignoreCols) {
for (String ignoreCol : ignoreCols) {
if (ignoreCol.equalsIgnoreCase(colName)) {
return true;
}
}
return false;
}
public <T> int updateBeanByCondition(T bean,
String condition, String tableName) throws Exception {
return updateBeanByCondition(bean, condition, tableName, new String[0]);
}
public <T> int updateBeanByCondition(T bean,
String condition, String tableName, String[] ignoreCols)
throws Exception {
// 分析bean中的数据
Class clazz = bean.getClass();
Map<String, Object> data = new LinkedHashMap<String, Object>();
Field[] fields = clazz.getDeclaredFields();
Method[] allMethods = clazz.getMethods();
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
String name = f.getName();
// 有需要忽略的列,则不生成指定的字段的sql
if (ignoreCols != null && isIgnoreCols(name, ignoreCols)) {
continue;
}
Method method = this.getMethod(allMethods,"get", name);
if (method != null) {
Object value = method.invoke(bean, new Object[0]);
if (value != null) {
data.put(f.getName() + "=?", value);
}
}
}
}
// 合成update SQL语句
String sql = "UPDATE " + tableName + " SET "
+ data.keySet().toString().replace("[", "").replace("]", "")
+ " WHERE " + condition;
return this.execute(sql.toString(), data.values().toArray());
}
public <T> int updateBean(T bean, String idcol,
String tableName, String[] ignoreCols) throws Exception {
// 分析bean中的数据
Class clazz = bean.getClass();
Map<String, Object> data = new LinkedHashMap<String, Object>();
Field[] fields = clazz.getDeclaredFields();
Method[] allMethods = clazz.getMethods();
Object idvalue = "";
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
String name = f.getName();
// 有需要忽略的列,则不生成指定的字段的sql
if (ignoreCols != null && isIgnoreCols(name, ignoreCols)) {
continue;
}
Method method = this.getMethod(allMethods,"get", name);
if (method != null) {
Object value = method.invoke(bean, new Object[0]);
data.put(f.getName() + "=?", value);
if (name.equals(idcol)) {// 获得ID条件
idvalue = value;
}
}
}
}
// 合成update SQL语句
String sql = "UPDATE " + tableName + " SET "
+ data.keySet().toString().replace("[", "").replace("]", "")
+ " WHERE " + idcol + "='" + idvalue + "'";
return this.execute(sql.toString(), data.values().toArray());
}
/**
* 执行批量sql语句
* @param sql
* @return
* @throws Exception
*/
public int[] excute(String[] sql) throws Exception {
Connection conn = getConnection();
Statement sta = null;
try {
sta = conn.createStatement();
for(String temp : sql) {
sta.addBatch(temp);
}
return sta.executeBatch();
} finally {
cleanup(sta);
closeConnection();
}
}
/**
* 执行批量sql语句
* @param sql
* @return
* @throws Exception
*/
public int[] excutePrepare(String sql, LinkedList<Object[]> params) throws Exception {
Connection conn = getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
int count = 1;
for(Object[] temp : params) {
int i = 1;
for(Object tp1 : temp) {
if(tp1 instanceof Integer) {
ps.setInt(i, (Integer) tp1);
} else if(tp1 instanceof Double) {
ps.setDouble(i, (Double) tp1);
} else if(tp1 instanceof String) {
ps.setString(i, (String) tp1);
} else if(tp1 instanceof Date) {
ps.setDate(i, (java.sql.Date) tp1);
}
i ++;
}
ps.addBatch();
if(count% 50 ==0) {
ps.executeBatch();
ps.clearBatch();
}
count ++;
}
return ps.executeBatch();
} finally {
cleanup(ps);
closeConnection();;
}
}
}
package com.kingdee.dao;
import org.springframework.stereotype.Component;
@Component("page")
public class MySQLPage implements IPage{
public String formatPageSQL(String sql, int offset, int limit) {
// TODO Auto-generated method stub
if(offset<0){
offset=0;
}
if(limit<0){
limit=0;
}
if(offset==0&&limit==0){
return sql;
}
if(offset>0&&limit==0){
limit = Integer.MAX_VALUE;
}
sql = sql + "limit " + offset + " , "+ limit;
return sql;
}
}
package com.kingdee.dao;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcUtil {
/**
*
* @param rs
* @param index
* @param requiredType
* @return
* @throws SQLException
*/
public static Object getResultSetValue(ResultSet rs, int index, Class requiredType) throws SQLException {
if (requiredType == null) {
return getResultSetValue(rs, index);
}
Object value = null;
boolean wasNullCheck = false;
// Explicitly extract typed value, as far as possible.
if (String.class.equals(requiredType)) {
value = rs.getString(index);
}
else if (boolean.class.equals(requiredType) || Boolean.class.equals(requiredType)) {
value = rs.getBoolean(index);
wasNullCheck = true;
}
else if (byte.class.equals(requiredType) || Byte.class.equals(requiredType)) {
value = rs.getByte(index);
wasNullCheck = true;
}
else if (short.class.equals(requiredType) || Short.class.equals(requiredType)) {
value = rs.getShort(index);
wasNullCheck = true;
}
else if (int.class.equals(requiredType) || Integer.class.equals(requiredType)) {
value = rs.getInt(index);
wasNullCheck = true;
}
else if (long.class.equals(requiredType) || Long.class.equals(requiredType)) {
value = rs.getLong(index);
wasNullCheck = true;
}
else if (float.class.equals(requiredType) || Float.class.equals(requiredType)) {
value = rs.getFloat(index);
wasNullCheck = true;
}
else if (double.class.equals(requiredType) || Double.class.equals(requiredType) ||
Number.class.equals(requiredType)) {
value = rs.getDouble(index);
wasNullCheck = true;
}
else if (byte[].class.equals(requiredType)) {
value = rs.getBytes(index);
}
else if (java.sql.Date.class.equals(requiredType)) {
value = rs.getDate(index);
}
else if (java.sql.Time.class.equals(requiredType)) {
value = rs.getTime(index);
}
else if (java.sql.Timestamp.class.equals(requiredType) || java.util.Date.class.equals(requiredType)) {
value = rs.getTimestamp(index);
}
else if (BigDecimal.class.equals(requiredType)) {
value = rs.getBigDecimal(index);
}
else if (Blob.class.equals(requiredType)) {
value = rs.getBlob(index);
}
else if (Clob.class.equals(requiredType)) {
value = rs.getClob(index);
}
else {
// Some unknown type desired -> rely on getObject.
value = getResultSetValue(rs, index);
}
// Perform was-null check if demanded (for results that the
// JDBC driver returns as primitives).
if (wasNullCheck && value != null && rs.wasNull()) {
value = null;
}
return value;
}
/**
* @see org.springframework.jdbc.support.JdbcUtils
* @param rs
* @param index
* @return
* @throws SQLException
*/
public static Object getResultSetValue(ResultSet rs, int index) throws SQLException {
return org.springframework.jdbc.support.JdbcUtils.getResultSetValue(rs, index);
}
}
package com.kingdee.dao;
public interface IPage {
public String formatPageSQL(String sql, int offset, int limit);
}