├── DbHelper ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── com │ │ └── opensource │ │ └── dbhelp │ │ ├── dialect │ │ ├── package-info.java │ │ ├── mysql │ │ │ ├── package-info.java │ │ │ └── MySqlPageParser.java │ │ ├── oracle │ │ │ ├── package-info.java │ │ │ └── OraclePageSqlParser.java │ │ ├── PageSqlParserFactory.java │ │ └── PageSqlParser.java │ │ ├── page │ │ ├── package-info.java │ │ ├── PageShow.java │ │ ├── ListPage.java │ │ ├── AbstractPagedStatement.java │ │ ├── DefaultPageShow.java │ │ ├── Page.java │ │ └── ListPagedStatement.java │ │ ├── package-info.java │ │ ├── dbutils │ │ ├── wrappers │ │ │ ├── package-info.java │ │ │ ├── StringTrimmedResultSet.java │ │ │ └── SqlNullCheckedResultSet.java │ │ ├── handlers │ │ │ ├── package-info.java │ │ │ ├── AbstractListHandler.java │ │ │ ├── ArrayListHandler.java │ │ │ ├── StringArrayListHandler.java │ │ │ ├── MapListHandler.java │ │ │ ├── StringMapListHandler.java │ │ │ ├── MapHandler.java │ │ │ ├── StringMapHandler.java │ │ │ ├── ArrayHandler.java │ │ │ ├── StringArrayHandler.java │ │ │ ├── BeanListHandler.java │ │ │ ├── BeanHandler.java │ │ │ ├── AbstractKeyedHandler.java │ │ │ ├── ColumnListHandler.java │ │ │ ├── ScalarHandler.java │ │ │ ├── KeyedHandler.java │ │ │ └── BeanMapHandler.java │ │ ├── package-info.java │ │ ├── ResultSetHandler.java │ │ ├── CamelBeanProcessor.java │ │ ├── StringRowProcessor.java │ │ ├── RowProcessor.java │ │ ├── QueryLoader.java │ │ ├── ResultSetIterator.java │ │ ├── ProxyFactory.java │ │ ├── BasicStringRowProcessor.java │ │ ├── BasicRowProcessor.java │ │ ├── DbUtils.java │ │ ├── AbstractQueryRunner.java │ │ └── BeanProcessor.java │ │ ├── DbHelperManager.java │ │ └── DbTransaction.java └── pom.xml └── README.md /DbHelper/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | .DS_Store 4 | /target 5 | *.iml 6 | *.log 7 | rebel.xml -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 对不同数据库类型进行个性化处理 * 3 | */ 4 | package com.opensource.dbhelp.dialect; -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/mysql/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * mysql数据库个性处理 * 3 | */ 4 | package com.opensource.dbhelp.dialect.mysql; -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/oracle/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * oracle数据库个性处理 * 3 | */ 4 | package com.opensource.dbhelp.dialect.oracle; -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 翻页实现。 3 | *

4 | * 通过调用PageFactory的方法获取封装好的翻页对象,用于在前台展示。 5 | */ 6 | package com.opensource.dbhelp.page; -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/PageShow.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | /** 4 | * 定义根据封装的分页对象获取页面展示分页导航html的接口。 5 | *

6 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 7 | *

8 | * Company: GNU General Public License 9 | *

10 | * Author: GNU General Public License 11 | *

12 | * Version: 1.0 13 | *

14 | */ 15 | public interface PageShow { 16 | 17 | /** 18 | * 获得分页导航HTML 19 | * 20 | * @param page 21 | * 分页对象 22 | * @return HTML字符,用于在前台展示分页导航 23 | */ 24 | public String getPageIndex(ListPage page); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 提供数据访问的封装。 3 | *

4 | * 5 | *

 6 |  * 
 7 |  * // 获取默认helper实例
 8 |  * DbHelper oracleDbHelper = DbHelperManager.getHelper();
 9 |  * 
10 |  * // oracle 数据库
11 |  * DbHelper oracleDbHelper = DbHelperManager.getInstance().getHelper("oracle", "oracle");
12 |  * 
13 |  * // mysql 数据库
14 |  * DbHelper mySqlDbHelper = DbHelperManager.getInstance().getHelper("mysql", "mysql");
15 |  * 
16 |  * // 事务对象
17 |  * DbTransaction transaction = mySqlDbHelper.getDbTransaction();
18 |  *
19 |  * 
20 | */ 21 | package com.opensource.dbhelp; -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/PageSqlParserFactory.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.dialect; 2 | 3 | import com.opensource.dbhelp.dialect.mysql.MySqlPageParser; 4 | import com.opensource.dbhelp.dialect.oracle.OraclePageSqlParser; 5 | 6 | /** 7 | * 获取翻页sql解析对象 8 | *

9 | * Copyright: Copyright (c) 13-1-15 上午9:27 10 | *

11 | * Company: GNU General Public License 12 | *

13 | * Author: GNU General Public License 14 | *

15 | * Version: 1.0 16 | *

17 | */ 18 | public class PageSqlParserFactory { 19 | 20 | /** 21 | * 获取翻页解析对象 22 | * 23 | * @param dialect 24 | * 数据库类型 25 | * @return PageSqlParser 26 | */ 27 | public static PageSqlParser getParser(String dialect) { 28 | if ("mysql".equals(dialect)) { 29 | return new MySqlPageParser(); 30 | } else { 31 | return new OraclePageSqlParser(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/wrappers/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | 5 | /** 6 | * Wrappers that add functionality to java.sql classes. 7 | */ 8 | package com.opensource.dbhelp.dbutils.wrappers; 9 | 10 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | 5 | /** 6 | * Implementations of the com.opensource.dbhelp.dbutils.ResultSetHandler interface. 7 | */ 8 | package com.opensource.dbhelp.dbutils.handlers; 9 | 10 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/PageSqlParser.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.dialect; 2 | 3 | /** 4 | * 翻页SQL接口 5 | *

6 | * Copyright: Copyright (c) 13-1-14 下午3:57 7 | *

8 | * Company: GNU General Public License 9 | *

10 | * Author: GNU General Public License 11 | *

12 | * Version: 1.0 13 | *

14 | */ 15 | public interface PageSqlParser { 16 | 17 | /** 18 | * 生成查询一页数据的sql语句 19 | * 20 | * @param sql 21 | * 原查询语句 22 | * @param hasOffset 23 | * true 不是第一页 false 第一页 24 | * @return 查询当前页的SQL 25 | */ 26 | public String getPageSql(String sql, boolean hasOffset); 27 | 28 | /** 29 | * 获取查询记录数的sql语句 30 | * 31 | * @param sql 32 | * 原查询语句 33 | * @return 查询记录数的SQL 34 | */ 35 | public String getCountingSql(String sql); 36 | 37 | /** 38 | * 附加翻页参数 39 | * 40 | * @param params 41 | * 原有参数 42 | * @param hasOffset 43 | * true 不是第一页 false 第一页 44 | * @param startIndex 45 | * 开始索引 46 | * @param pageSize 47 | * 每页记录数 48 | * @return 附加翻页后的传入参数 49 | */ 50 | public Object[] attachPageParam(Object[] params, boolean hasOffset, int startIndex, int pageSize); 51 | } 52 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/mysql/MySqlPageParser.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.dialect.mysql; 2 | 3 | import org.apache.commons.lang3.ArrayUtils; 4 | 5 | import com.opensource.dbhelp.dialect.PageSqlParser; 6 | 7 | /** 8 | * Mysql 翻页接口实现 9 | *

10 | * Copyright: Copyright (c) 13-1-14 下午4:01 11 | *

12 | * Company: GNU General Public License 13 | *

14 | * Author: GNU General Public License 15 | *

16 | * Version: 1.0 17 | *

18 | */ 19 | public class MySqlPageParser implements PageSqlParser { 20 | 21 | @Override 22 | public String getPageSql(String sql, boolean hasOffset) { 23 | if (hasOffset) { 24 | return sql + " limit ?, ?"; 25 | } else { 26 | return sql + " limit ?"; 27 | } 28 | } 29 | 30 | @Override 31 | public String getCountingSql(String sql) { 32 | return "select count(1) from ( " + sql + ") as __tc"; 33 | } 34 | 35 | @Override 36 | public Object[] attachPageParam(Object[] params, boolean hasOffset, int startIndex, int pageSize) { 37 | if (hasOffset) { 38 | params = ArrayUtils.add(params, startIndex - 1); 39 | params = ArrayUtils.add(params, pageSize); 40 | } else { 41 | params = ArrayUtils.add(params, pageSize); 42 | } 43 | return params; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | 5 | /** 6 | * DbUtils is a small set of classes designed to make working with JDBC easier. JDBC resource cleanup code is mundane, error prone work so these classes abstract out all of the cleanup tasks from your code leaving you with what you really wanted to do with JDBC in the first place: query and update data. This package contains the core classes and interfaces - DbUtils, QueryRunner and the ResultSetHandler interface should be your first items of interest. 7 | */ 8 | package com.opensource.dbhelp.dbutils; 9 | 10 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dialect/oracle/OraclePageSqlParser.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.dialect.oracle; 2 | 3 | import org.apache.commons.lang3.ArrayUtils; 4 | 5 | import com.opensource.dbhelp.dialect.PageSqlParser; 6 | 7 | /** 8 | * Oracle 翻页接口实现 9 | *

10 | * Copyright: Copyright (c) 13-1-14 下午3:57 11 | *

12 | * Company: GNU General Public License 13 | *

14 | * Author: GNU General Public License 15 | *

16 | * Version: 1.0 17 | *

18 | */ 19 | public class OraclePageSqlParser implements PageSqlParser { 20 | 21 | @Override 22 | public String getPageSql(String sql, boolean hasOffset) { 23 | StringBuilder ret = new StringBuilder(sql.length() + 100); 24 | if (hasOffset) { 25 | ret.append("select * from ( select row_.*, rownum rownum_ from ( "); 26 | } else { 27 | ret.append("select * from ( "); 28 | } 29 | ret.append(sql); 30 | if (hasOffset) { 31 | ret.append(" ) row_ where rownum < ?) where rownum_ >= ?"); 32 | } else { 33 | ret.append(" ) where rownum < ?"); 34 | } 35 | return ret.toString(); 36 | } 37 | 38 | @Override 39 | public String getCountingSql(String sql) { 40 | return "select count(1) from ( " + sql + ")"; 41 | } 42 | 43 | @Override 44 | public Object[] attachPageParam(Object[] params, boolean hasOffset, int startIndex, int pageSize) { 45 | if (hasOffset) { 46 | params = ArrayUtils.add(params, startIndex + pageSize); 47 | params = ArrayUtils.add(params, startIndex); 48 | } else { 49 | params = ArrayUtils.add(params, startIndex + pageSize); 50 | } 51 | return params; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/ResultSetHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * Implementations of this interface convert ResultSets into other objects. 11 | * 12 | * @param 13 | * the target type the input ResultSet will be converted to. 14 | */ 15 | public interface ResultSetHandler { 16 | 17 | /** 18 | * Turn the ResultSet into an Object. 19 | * 20 | * @param rs 21 | * The ResultSet to handle. It has not been touched before being passed to this method. 22 | * @return An Object initialized with ResultSet data. It is legal for implementations to return null if the ResultSet contained 0 rows. 23 | * @throws java.sql.SQLException 24 | * if a database access error occurs 25 | */ 26 | T handle(ResultSet rs) throws SQLException; 27 | 28 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/ListPage.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 使用List封装数据的分页对象。 8 | *

9 | *

10 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 11 | *

12 | * Company: GNU General Public License 13 | *

14 | * Author: GNU General Public License 15 | *

16 | * Version: 1.0 17 | *

18 | */ 19 | public class ListPage extends Page { 20 | 21 | /** serialVersionUID */ 22 | private static final long serialVersionUID = 3066553667648785439L; 23 | 24 | /** 包含记录的List对象 */ 25 | private List list; 26 | 27 | /** 28 | * 默认构造方法,创建空页 29 | */ 30 | public ListPage() { 31 | this(new ArrayList(), 0, 0); 32 | } 33 | 34 | /** 35 | * 构造分页对象 36 | * 37 | * @param data 38 | * 包含一页数据的OracleCachedRowSet 39 | * @param start 40 | * 该页数据在数据库中的起始位置 41 | * @param totalSize 42 | * 数据库中包含的记录总数 43 | */ 44 | public ListPage(List data, int start, int totalSize) { 45 | this(data, start, totalSize, Page.DEFAULT_PAGESIZE); 46 | } 47 | 48 | /** 49 | * 构造分页对象 50 | * 51 | * @param data 52 | * 包含一页数据的OracleCachedRowSet 53 | * @param start 54 | * 该页数据在数据库中的起始位置 55 | * @param totalSize 56 | * 数据库中包含的记录总数 57 | * @param pageSize 58 | * 本页能容纳的记录数 59 | */ 60 | public ListPage(List data, int start, int totalSize, int pageSize) { 61 | this.list = data; 62 | super.init(start, (data == null) ? 0 : data.size(), totalSize, pageSize, this.list); 63 | } 64 | 65 | /** 66 | * 取分页对象中的记录数据 67 | * 68 | * @return 包含记录的List对象 69 | */ 70 | public List getList() { 71 | return this.list; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /DbHelper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.opensource 5 | dbhelper 6 | 0.0.2-SNAPSHOT 7 | DbHelper是支持定制化SQL、存储过程以及高级映射的高效性持久层框架,其主要就完成2件事情:封装JDBC操作;利用反射打通Java类与SQL语句之间的相互转换。DbHelper的主要设计目的是让我们对执行SQL语句时对输入输出的数据管理更加方便,高效快捷地写出SQL和方便地获取SQL的执行结果。 8 | 9 | 10 | src/main/java 11 | 12 | 13 | maven-compiler-plugin 14 | 3.3 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | com.mchange 27 | c3p0 28 | 0.9.5.4 29 | 30 | 31 | 32 | org.apache.commons 33 | commons-lang3 34 | 3.8.1 35 | 36 | 37 | 38 | commons-logging 39 | commons-logging 40 | 1.2 41 | 42 | 43 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/DbHelperManager.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import com.mchange.v2.c3p0.ComboPooledDataSource; 9 | 10 | /** 11 | * 管理DbHelper实例。 12 | *

13 | * Copyright: Copyright (c) 13-1-14 下午2:08 14 | *

15 | * Company: GNU General Public License 16 | *

17 | * Author: GNU General Public License 18 | *

19 | * Version: 1.0 20 | *

21 | */ 22 | public class DbHelperManager { 23 | 24 | private DbHelperManager() { 25 | // disable construct 26 | } 27 | 28 | private final static DbHelperManager INSTANCE = new DbHelperManager(); 29 | 30 | /** 31 | * construct 32 | * 33 | * @return DbHelperManager实例 34 | */ 35 | public static DbHelperManager getInstance() { 36 | return INSTANCE; 37 | } 38 | 39 | private final Map helpers = new HashMap(); 40 | 41 | /** 42 | * 获得DbHelper实例 43 | * 44 | * @param configName 45 | * 数据源名 46 | * @return DbHelper 47 | */ 48 | public DbHelper getHelper(String configName, String dialect) { 49 | synchronized (helpers) { 50 | if (helpers.containsKey(configName)) { 51 | return helpers.get(configName); 52 | } else { 53 | DataSource dataSource = new ComboPooledDataSource(configName); 54 | DbHelper dbHelper = new DbHelper(dataSource); 55 | if ("mysql".equals(dialect)) { 56 | dbHelper.setDialect("mysql"); 57 | } else { 58 | dbHelper.setDialect("oracle"); 59 | } 60 | helpers.put(configName, dbHelper); 61 | return dbHelper; 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * 获取默认数据库helper对象 68 | * 69 | * @return DbHelper 70 | */ 71 | public static DbHelper getHelper() { 72 | return DbHelperManager.getInstance().getHelper(null, null); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/AbstractPagedStatement.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | import java.sql.SQLException; 4 | 5 | import com.opensource.dbhelp.dialect.PageSqlParser; 6 | import com.opensource.dbhelp.dialect.PageSqlParserFactory; 7 | 8 | /** 9 | * 分页查询。 10 | *

11 | * 根据查询语句和页码查询出当页数据。 12 | *

13 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 14 | *

15 | * Company: GNU General Public License 16 | *

17 | * Author: GNU General Public License 18 | *

19 | * Version: 1.0 20 | *

21 | */ 22 | public abstract class AbstractPagedStatement { 23 | 24 | /** 每页允许的最大记录数 */ 25 | public final static int MAX_PAGESIZE = Page.MAX_PAGESIZE; 26 | 27 | /** 查询总记录数的SQL */ 28 | protected String countSql; 29 | 30 | /** 查询SQL */ 31 | protected String querySql; 32 | 33 | /** 当前显示页 */ 34 | protected int currentPage; 35 | 36 | /** 每页记录数 */ 37 | protected int pageSize; 38 | 39 | /** 当前显示页从记录集开始的位置 */ 40 | protected int startIndex; 41 | 42 | /** 总记录数 */ 43 | protected int totalCount; 44 | 45 | /** 显示当前页是否需要偏移 */ 46 | protected boolean hasOffset; 47 | 48 | protected PageSqlParser pageSqlParser; 49 | 50 | /** 51 | * 构造一查询出当页数据的PageStatement,并指定每页显示记录条数 52 | * 53 | * @param dialect 54 | * database dialect 55 | * @param sql 56 | * query sql 57 | * @param currentPage 58 | * 页码 59 | * @param pageSize 60 | * 每页容量 61 | */ 62 | public AbstractPagedStatement(String dialect, String sql, int currentPage, int pageSize) { 63 | this.currentPage = currentPage; 64 | this.pageSize = pageSize; 65 | this.startIndex = Page.getStartOfAnyPage(currentPage, pageSize); 66 | this.hasOffset = currentPage > 1; 67 | 68 | pageSqlParser = PageSqlParserFactory.getParser(dialect); 69 | this.countSql = pageSqlParser.getCountingSql(sql); 70 | this.querySql = pageSqlParser.getPageSql(sql, hasOffset); 71 | } 72 | 73 | /** 74 | * 执行查询 75 | * 76 | * @param type 77 | * 预定义的查询类型,会返回不同类型分页对象 78 | * @return 分页对象 79 | * @throws SQLException 80 | * if a database access error occurs 81 | */ 82 | protected abstract Page executeQuery(int type) throws SQLException; 83 | 84 | } 85 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/CamelBeanProcessor.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.dbutils; 2 | 3 | import java.beans.PropertyDescriptor; 4 | import java.sql.ResultSetMetaData; 5 | import java.sql.SQLException; 6 | import java.util.Arrays; 7 | 8 | import org.apache.commons.lang3.text.WordUtils; 9 | 10 | /** 11 | * 记录集字段及bean属性之间的映射转换实现类。 12 | *

13 | * 重写dbutils中“beanProcessor”的"mapColumnsToProperties"方法, 使其可以实现数据表user_id到对象userId和user_id到对象属性user_id之间的自动转换。 注:引用时需要注意的是平台优先处理“user_id到对象userId”。 14 | *

15 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 16 | *

17 | * Company: GNU General Public License 18 | *

19 | * Author: GNU General Public License 20 | *

21 | * Version: 1.1 22 | *

23 | */ 24 | public class CamelBeanProcessor extends BeanProcessor { 25 | 26 | /** 27 | * 对象属性和字段关系映射 28 | * 29 | * @param rsmd 30 | * 元字符结果集 31 | * @param props 32 | * 对象属性数组 33 | * @return 对象和数据表字段关系位置数组 34 | */ 35 | @Override 36 | protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, PropertyDescriptor[] props) throws SQLException { 37 | 38 | int cols = rsmd.getColumnCount(); 39 | int columnToProperty[] = new int[cols + 1]; 40 | Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND); 41 | 42 | for (int col = 1; col <= cols; col++) { 43 | String columnName = rsmd.getColumnLabel(col); 44 | if (null == columnName || 0 == columnName.length()) { 45 | columnName = rsmd.getColumnName(col); 46 | } 47 | 48 | for (int i = 0; i < props.length; i++) { 49 | if (formatColName(columnName).equalsIgnoreCase(props[i].getName())) { 50 | columnToProperty[col] = i; 51 | break; 52 | } 53 | if (columnName.equalsIgnoreCase(props[i].getName())) { 54 | columnToProperty[col] = i; 55 | break; 56 | } 57 | } 58 | } 59 | 60 | return columnToProperty; 61 | } 62 | 63 | /** 64 | * 格式化字符将user_id或USER_ID字段返回成userId 65 | * 66 | * @param name 67 | * 字段名 68 | * @return 转化后的属性名 69 | */ 70 | private String formatColName(String name) { 71 | if (name == null || "".equals(name)) { 72 | return ""; 73 | } 74 | String rstr = name.toLowerCase(); 75 | rstr = WordUtils.uncapitalize(WordUtils.capitalize(rstr, "_".toCharArray())); 76 | rstr = rstr.replaceAll("_", ""); 77 | return rstr; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/StringRowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | /** 11 | * StringRowProcessor implementations convert ResultSet rows into various other objects. Implementations can extend BasicStringRowProcessor to protect themselves from changes to this interface. 12 | * 13 | * @see BasicStringRowProcessor 14 | */ 15 | public interface StringRowProcessor { 16 | 17 | /** 18 | * Create an String[] from the column values in one ResultSet row. The ResultSet should be positioned on a valid row before passing it to this method. Implementations of this method must not alter the row position of the ResultSet. 19 | * 20 | * @param rs 21 | * ResultSet that supplies the array data 22 | * @throws java.sql.SQLException 23 | * if a database access error occurs 24 | * @return the newly created array 25 | */ 26 | String[] toArray(ResultSet rs) throws SQLException; 27 | 28 | /** 29 | * Create a Map from the column values in one ResultSet row. The ResultSet should be positioned on a valid row before passing it to this method. Implementations of this method must not alter the row position of the ResultSet. 30 | * 31 | * @param rs 32 | * ResultSet that supplies the map data 33 | * @throws java.sql.SQLException 34 | * if a database access error occurs 35 | * @return the newly created Map 36 | */ 37 | Map toMap(ResultSet rs) throws SQLException; 38 | 39 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/AbstractListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 12 | 13 | /** 14 | * Abstract class that simplify development of ResultSetHandler classes that convert ResultSet into List. 15 | * 16 | * @param 17 | * the target List generic type 18 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 19 | */ 20 | public abstract class AbstractListHandler implements ResultSetHandler> { 21 | 22 | /** 23 | * Whole ResultSet handler. It produce List as result. To convert individual rows into Java objects it uses handleRow(ResultSet) method. 24 | * 25 | * @see #handleRow(java.sql.ResultSet) 26 | * @param rs 27 | * ResultSet to process. 28 | * @return a list of all rows in the result set 29 | * @throws java.sql.SQLException 30 | * error occurs 31 | */ 32 | @Override 33 | public List handle(ResultSet rs) throws SQLException { 34 | List rows = new ArrayList(); 35 | while (rs.next()) { 36 | rows.add(this.handleRow(rs)); 37 | } 38 | return rows; 39 | } 40 | 41 | /** 42 | * Row handler. Method converts current row into some Java object. 43 | * 44 | * @param rs 45 | * ResultSet to process. 46 | * @return row processing result 47 | * @throws java.sql.SQLException 48 | * error occurs 49 | */ 50 | protected abstract T handleRow(ResultSet rs) throws SQLException; 51 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/ArrayListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.RowProcessor; 10 | 11 | /** 12 | * ResultSetHandler implementation that converts the ResultSet into a List of Object[]s. This class is thread safe. 13 | * 14 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 15 | */ 16 | public class ArrayListHandler extends AbstractListHandler { 17 | 18 | /** 19 | * The RowProcessor implementation to use when converting rows into Object[]s. 20 | */ 21 | private final RowProcessor convert; 22 | 23 | /** 24 | * Creates a new instance of ArrayListHandler using a BasicRowProcessor for conversions. 25 | */ 26 | public ArrayListHandler() { 27 | this(ArrayHandler.ROW_PROCESSOR); 28 | } 29 | 30 | /** 31 | * Creates a new instance of ArrayListHandler. 32 | * 33 | * @param convert 34 | * The RowProcessor implementation to use when converting rows into Object[]s. 35 | */ 36 | public ArrayListHandler(RowProcessor convert) { 37 | super(); 38 | this.convert = convert; 39 | } 40 | 41 | /** 42 | * Convert row's columns into an Object[]. 43 | * 44 | * @param rs 45 | * ResultSet to process. 46 | * @return Object[], never null. 47 | * @throws java.sql.SQLException 48 | * if a database access error occurs 49 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractListHandler#handle(java.sql.ResultSet) 50 | */ 51 | @Override 52 | protected Object[] handleRow(ResultSet rs) throws SQLException { 53 | return this.convert.toArray(rs); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/StringArrayListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.StringRowProcessor; 10 | 11 | /** 12 | * ResultSetHandler implementation that converts the ResultSet into a List of String[]s. This class is thread safe. 13 | * 14 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 15 | */ 16 | public class StringArrayListHandler extends AbstractListHandler { 17 | 18 | /** 19 | * The StringRowProcessor implementation to use when converting rows into String[]s. 20 | */ 21 | private final StringRowProcessor convert; 22 | 23 | /** 24 | * Creates a new instance of ArrayListHandler using a BasicStringRowProcessor for conversions. 25 | */ 26 | public StringArrayListHandler() { 27 | this(StringArrayHandler.ROW_PROCESSOR); 28 | } 29 | 30 | /** 31 | * Creates a new instance of ArrayListHandler. 32 | * 33 | * @param convert 34 | * The StringRowProcessor implementation to use when converting rows into String[]s. 35 | */ 36 | public StringArrayListHandler(StringRowProcessor convert) { 37 | super(); 38 | this.convert = convert; 39 | } 40 | 41 | /** 42 | * Convert row's columns into an Object[]. 43 | * 44 | * @return Object[], never null. 45 | * @throws java.sql.SQLException 46 | * if a database access error occurs 47 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractListHandler#handle(java.sql.ResultSet) 48 | */ 49 | @Override 50 | protected String[] handleRow(ResultSet rs) throws SQLException { 51 | return this.convert.toArray(rs); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/MapListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | import com.opensource.dbhelp.dbutils.RowProcessor; 11 | 12 | /** 13 | * ResultSetHandler implementation that converts a ResultSet into a List of Maps. This class is thread safe. 14 | * 15 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 16 | */ 17 | public class MapListHandler extends AbstractListHandler> { 18 | 19 | /** 20 | * The RowProcessor implementation to use when converting rows into Maps. 21 | */ 22 | private final RowProcessor convert; 23 | 24 | /** 25 | * Creates a new instance of MapListHandler using a BasicRowProcessor for conversion. 26 | */ 27 | public MapListHandler() { 28 | this(ArrayHandler.ROW_PROCESSOR); 29 | } 30 | 31 | /** 32 | * Creates a new instance of MapListHandler. 33 | * 34 | * @param convert 35 | * The RowProcessor implementation to use when converting rows into Maps. 36 | */ 37 | public MapListHandler(RowProcessor convert) { 38 | super(); 39 | this.convert = convert; 40 | } 41 | 42 | /** 43 | * Converts the ResultSet row into a Map object. 44 | * 45 | * @param rs 46 | * ResultSet to process. 47 | * @return A Map, never null. 48 | * @throws java.sql.SQLException 49 | * if a database access error occurs 50 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractListHandler#handle(java.sql.ResultSet) 51 | */ 52 | @Override 53 | protected Map handleRow(ResultSet rs) throws SQLException { 54 | return this.convert.toMap(rs); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/StringMapListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | import com.opensource.dbhelp.dbutils.StringRowProcessor; 11 | 12 | /** 13 | * ResultSetHandler implementation that converts a ResultSet into a List of Maps. This class is thread safe. 14 | * 15 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 16 | */ 17 | public class StringMapListHandler extends AbstractListHandler> { 18 | 19 | /** 20 | * The StringRowProcessor implementation to use when converting rows into Maps. 21 | */ 22 | private final StringRowProcessor convert; 23 | 24 | /** 25 | * Creates a new instance of MapListHandler using a BasicStringRowProcessor for conversion. 26 | */ 27 | public StringMapListHandler() { 28 | this(StringArrayHandler.ROW_PROCESSOR); 29 | } 30 | 31 | /** 32 | * Creates a new instance of MapListHandler. 33 | * 34 | * @param convert 35 | * The StringRowProcessor implementation to use when converting rows into Maps. 36 | */ 37 | public StringMapListHandler(StringRowProcessor convert) { 38 | super(); 39 | this.convert = convert; 40 | } 41 | 42 | /** 43 | * Converts the ResultSet row into a Map object. 44 | * 45 | * @return A Map, never null. 46 | * @throws java.sql.SQLException 47 | * if a database access error occurs 48 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractListHandler#handle(java.sql.ResultSet) 49 | */ 50 | @Override 51 | protected Map handleRow(ResultSet rs) throws SQLException { 52 | return this.convert.toMap(rs); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/MapHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 11 | import com.opensource.dbhelp.dbutils.RowProcessor; 12 | 13 | /** 14 | * ResultSetHandler implementation that converts the first ResultSet row into a Map. This class is thread safe. 15 | * 16 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 17 | */ 18 | public class MapHandler implements ResultSetHandler> { 19 | 20 | /** 21 | * The RowProcessor implementation to use when converting rows into Maps. 22 | */ 23 | private final RowProcessor convert; 24 | 25 | /** 26 | * Creates a new instance of MapHandler using a BasicRowProcessor for conversion. 27 | */ 28 | public MapHandler() { 29 | this(ArrayHandler.ROW_PROCESSOR); 30 | } 31 | 32 | /** 33 | * Creates a new instance of MapHandler. 34 | * 35 | * @param convert 36 | * The RowProcessor implementation to use when converting rows into Maps. 37 | */ 38 | public MapHandler(RowProcessor convert) { 39 | super(); 40 | this.convert = convert; 41 | } 42 | 43 | /** 44 | * Converts the first row in the ResultSet into a Map. 45 | * 46 | * @param rs 47 | * ResultSet to process. 48 | * @return A Map with the values from the first row or null if there are no rows in the ResultSet. 49 | * @throws java.sql.SQLException 50 | * if a database access error occurs 51 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 52 | */ 53 | @Override 54 | public Map handle(ResultSet rs) throws SQLException { 55 | return rs.next() ? this.convert.toMap(rs) : null; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/StringMapHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 11 | import com.opensource.dbhelp.dbutils.StringRowProcessor; 12 | 13 | /** 14 | * ResultSetHandler implementation that converts the first ResultSet row into a Map. This class is thread safe. 15 | * 16 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 17 | */ 18 | public class StringMapHandler implements ResultSetHandler> { 19 | 20 | /** 21 | * The StringRowProcessor implementation to use when converting rows into Maps. 22 | */ 23 | private final StringRowProcessor convert; 24 | 25 | /** 26 | * Creates a new instance of MapHandler using a BasicStringRowProcessor for conversion. 27 | */ 28 | public StringMapHandler() { 29 | this(StringArrayHandler.ROW_PROCESSOR); 30 | } 31 | 32 | /** 33 | * Creates a new instance of MapHandler. 34 | * 35 | * @param convert 36 | * The StringRowProcessor implementation to use when converting rows into Maps. 37 | */ 38 | public StringMapHandler(StringRowProcessor convert) { 39 | super(); 40 | this.convert = convert; 41 | } 42 | 43 | /** 44 | * Converts the first row in the ResultSet into a Map. 45 | * 46 | * @return A Map with the values from the first row or null if there are no rows in the ResultSet. 47 | * @throws java.sql.SQLException 48 | * if a database access error occurs 49 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 50 | */ 51 | @Override 52 | public Map handle(ResultSet rs) throws SQLException { 53 | return rs.next() ? this.convert.toMap(rs) : null; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/ArrayHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.BasicRowProcessor; 10 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 11 | import com.opensource.dbhelp.dbutils.RowProcessor; 12 | 13 | /** 14 | * ResultSetHandler implementation that converts a ResultSet into an Object[]. This class is thread safe. 15 | * 16 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 17 | */ 18 | public class ArrayHandler implements ResultSetHandler { 19 | 20 | /** 21 | * Singleton processor instance that handlers share to save memory. Notice the default scoping to allow only classes in this package to use this instance. 22 | */ 23 | static final RowProcessor ROW_PROCESSOR = new BasicRowProcessor(); 24 | 25 | /** 26 | * The RowProcessor implementation to use when converting rows into arrays. 27 | */ 28 | private final RowProcessor convert; 29 | 30 | /** 31 | * Creates a new instance of ArrayHandler using a BasicRowProcessor for conversion. 32 | */ 33 | public ArrayHandler() { 34 | this(ROW_PROCESSOR); 35 | } 36 | 37 | /** 38 | * Creates a new instance of ArrayHandler. 39 | * 40 | * @param convert 41 | * The RowProcessor implementation to use when converting rows into arrays. 42 | */ 43 | public ArrayHandler(RowProcessor convert) { 44 | super(); 45 | this.convert = convert; 46 | } 47 | 48 | /** 49 | * Places the column values from the first row in an Object[]. 50 | * 51 | * @param rs 52 | * ResultSet to process. 53 | * @return An Object[] or null if there are no rows in the ResultSet. 54 | * @throws java.sql.SQLException 55 | * if a database access error occurs 56 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 57 | */ 58 | @Override 59 | public Object[] handle(ResultSet rs) throws SQLException { 60 | return rs.next() ? this.convert.toArray(rs) : null; 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/StringArrayHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.BasicStringRowProcessor; 10 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 11 | import com.opensource.dbhelp.dbutils.StringRowProcessor; 12 | 13 | /** 14 | * ResultSetHandler implementation that converts a ResultSet into an String[]. This class is thread safe. 15 | * 16 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 17 | */ 18 | public class StringArrayHandler implements ResultSetHandler { 19 | 20 | /** 21 | * Singleton processor instance that handlers share to save memory. Notice the default scoping to allow only classes in this package to use this instance. 22 | */ 23 | static final StringRowProcessor ROW_PROCESSOR = new BasicStringRowProcessor(); 24 | 25 | /** 26 | * The StringRowProcessor implementation to use when converting rows into arrays. 27 | */ 28 | private final StringRowProcessor convert; 29 | 30 | /** 31 | * Creates a new instance of ArrayHandler using a BasicRowProcessor for conversion. 32 | */ 33 | public StringArrayHandler() { 34 | this(ROW_PROCESSOR); 35 | } 36 | 37 | /** 38 | * Creates a new instance of ArrayHandler. 39 | * 40 | * @param convert 41 | * The StringRowProcessor implementation to use when converting rows into arrays. 42 | */ 43 | public StringArrayHandler(StringRowProcessor convert) { 44 | super(); 45 | this.convert = convert; 46 | } 47 | 48 | /** 49 | * Places the column values from the first row in an Object[]. 50 | * 51 | * @return An Object[] or null if there are no rows in the ResultSet. 52 | * @throws java.sql.SQLException 53 | * if a database access error occurs 54 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 55 | */ 56 | @Override 57 | public String[] handle(ResultSet rs) throws SQLException { 58 | return rs.next() ? this.convert.toArray(rs) : null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/BeanListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 11 | import com.opensource.dbhelp.dbutils.RowProcessor; 12 | 13 | /** 14 | * ResultSetHandler implementation that converts a ResultSet into a List of beans. This class is thread safe. 15 | * 16 | * @param 17 | * the target bean type 18 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 19 | */ 20 | public class BeanListHandler implements ResultSetHandler> { 21 | 22 | /** 23 | * The Class of beans produced by this handler. 24 | */ 25 | private final Class type; 26 | 27 | /** 28 | * The RowProcessor implementation to use when converting rows into beans. 29 | */ 30 | private final RowProcessor convert; 31 | 32 | /** 33 | * Creates a new instance of BeanListHandler. 34 | * 35 | * @param type 36 | * The Class that objects returned from handle() are created from. 37 | */ 38 | public BeanListHandler(Class type) { 39 | this(type, ArrayHandler.ROW_PROCESSOR); 40 | } 41 | 42 | /** 43 | * Creates a new instance of BeanListHandler. 44 | * 45 | * @param type 46 | * The Class that objects returned from handle() are created from. 47 | * @param convert 48 | * The RowProcessor implementation to use when converting rows into beans. 49 | */ 50 | public BeanListHandler(Class type, RowProcessor convert) { 51 | this.type = type; 52 | this.convert = convert; 53 | } 54 | 55 | /** 56 | * Convert the whole ResultSet into a List of beans with the Class given in the constructor. 57 | * 58 | * @param rs 59 | * The ResultSet to handle. 60 | * @return A List of beans, never null. 61 | * @throws java.sql.SQLException 62 | * if a database access error occurs 63 | * @see com.opensource.dbhelp.dbutils.RowProcessor#toBeanList(java.sql.ResultSet, Class) 64 | */ 65 | @Override 66 | public List handle(ResultSet rs) throws SQLException { 67 | return this.convert.toBeanList(rs, type); 68 | } 69 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/BeanHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 10 | import com.opensource.dbhelp.dbutils.RowProcessor; 11 | 12 | /** 13 | * ResultSetHandler implementation that converts the first ResultSet row into a JavaBean. This class is thread safe. 14 | * 15 | * @param 16 | * the target bean type 17 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 18 | */ 19 | public class BeanHandler implements ResultSetHandler { 20 | 21 | /** 22 | * The Class of beans produced by this handler. 23 | */ 24 | private final Class type; 25 | 26 | /** 27 | * The RowProcessor implementation to use when converting rows into beans. 28 | */ 29 | private final RowProcessor convert; 30 | 31 | /** 32 | * Creates a new instance of BeanHandler. 33 | * 34 | * @param type 35 | * The Class that objects returned from handle() are created from. 36 | */ 37 | public BeanHandler(Class type) { 38 | this(type, ArrayHandler.ROW_PROCESSOR); 39 | } 40 | 41 | /** 42 | * Creates a new instance of BeanHandler. 43 | * 44 | * @param type 45 | * The Class that objects returned from handle() are created from. 46 | * @param convert 47 | * The RowProcessor implementation to use when converting rows into beans. 48 | */ 49 | public BeanHandler(Class type, RowProcessor convert) { 50 | this.type = type; 51 | this.convert = convert; 52 | } 53 | 54 | /** 55 | * Convert the first row of the ResultSet into a bean with the Class given in the constructor. 56 | * 57 | * @param rs 58 | * ResultSet to process. 59 | * @return An initialized JavaBean or null if there were no rows in the ResultSet. 60 | * @throws java.sql.SQLException 61 | * if a database access error occurs 62 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 63 | */ 64 | @Override 65 | public T handle(ResultSet rs) throws SQLException { 66 | return rs.next() ? this.convert.toBean(rs, this.type) : null; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DbHelper 2 | DbHelper是支持定制化SQL、存储过程以及高级映射的高效性轻量级持久层框架,其主要就完成2件事情:封装JDBC操作;利用反射打通Java类与SQL语句之间的相互转换。DbHelper的主要设计目的是让我们对执行SQL语句时对输入输出的数据管理更加方便,高效快捷地写出SQL和方便地获取SQL的执行结果。经过长期的维护,目前DbHelper支持返回的数据类型基本囊括了各种项目所需,包括分页、POJO、Array、Map、List\、List\、List\、List\等等,以及其他各种数据类型。 3 | # 使用方法 4 | 1. 克隆源码到本地maven项目,并打包到maven仓库,在具体项目中引入jar包: 5 | ``` 6 | 7 | com.opensource 8 | dbhelper 9 | 1.0.0 10 | 11 | ``` 12 | 2. 在Spring配置文件里配置DbHelper: 13 | ``` 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |   50 | 51 | 52 | 53 | ``` 54 | 3. 在DAO层注入DbHelper并使用: 55 | ``` 56 | public class TeseDao { 57 | 58 | @Autowired 59 | private DbHelper dbHelper; 60 | 61 | /** 62 | * 查询用户列表 63 | * 64 | * @param user 65 | * @return 66 | * @throws SQLException 67 | */ 68 | public List getUserList(User user) throws SQLException { 69 | StringBuilder sql = new StringBuilder(); 70 | List params = new ArrayList(); 71 | sql.append("SELECT TU.* FROM T_USER TU\n"); 72 | sql.append(" WHERE 1 = 1\n"); 73 | if (user != null && StringUtils.isNotEmpty(user.getName)) { 74 | sql.append(" AND TU.NAME LIKE ?\n"); 75 | params.add("%" + param.getName().trim() + "%"); 76 | } 77 | return dbHelper.getBeanList(sql.toString(), User.class, params.toArray()); 78 | } 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/AbstractKeyedHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 12 | 13 | /** 14 | *

15 | * ResultSetHandler implementation that returns a Map. ResultSet rows are converted into objects (Vs) which are then stored in a Map under the given keys (Ks). 16 | *

17 | * 18 | * @param 19 | * the type of keys maintained by the returned map 20 | * @param 21 | * the type of mapped values 22 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 23 | * @since DbUtils 1.3 24 | */ 25 | public abstract class AbstractKeyedHandler implements ResultSetHandler> { 26 | 27 | /** 28 | * Convert each row's columns into a Map and store then in a Map under ResultSet.getObject(key) key. 29 | * 30 | * @param rs 31 | * ResultSet to process. 32 | * @return A Map, never null. 33 | * @throws java.sql.SQLException 34 | * if a database access error occurs 35 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 36 | */ 37 | @Override 38 | public Map handle(ResultSet rs) throws SQLException { 39 | Map result = createMap(); 40 | while (rs.next()) { 41 | result.put(createKey(rs), createRow(rs)); 42 | } 43 | return result; 44 | } 45 | 46 | /** 47 | * This factory method is called by handle() to create the Map to store records in. This implementation returns a HashMap instance. 48 | * 49 | * @return Map to store records in 50 | */ 51 | protected Map createMap() { 52 | return new HashMap(); 53 | } 54 | 55 | /** 56 | * This factory method is called by handle() to retrieve the key value from the current ResultSet row. 57 | * 58 | * @param rs 59 | * ResultSet to create a key from 60 | * @return K from the configured key column name/index 61 | * @throws java.sql.SQLException 62 | * if a database access error occurs 63 | */ 64 | protected abstract K createKey(ResultSet rs) throws SQLException; 65 | 66 | /** 67 | * This factory method is called by handle() to store the current ResultSet row in some object. 68 | * 69 | * @param rs 70 | * ResultSet to create a row from 71 | * @return V object created from the current row 72 | * @throws java.sql.SQLException 73 | * if a database access error occurs 74 | */ 75 | protected abstract V createRow(ResultSet rs) throws SQLException; 76 | 77 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/DefaultPageShow.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | /** 10 | * PageShow的默认实现, 获取前台显示的分页导航。 11 | *

12 | *

13 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 14 | *

15 | * Company: GNU General Public License 16 | *

17 | * Author: GNU General Public License 18 | *

19 | * Version: 1.0 20 | *

21 | */ 22 | public class DefaultPageShow implements PageShow { 23 | 24 | /** 25 | * @see com.opensource.dbhelp.page.PageShow#getPageIndex(ListPage) 26 | */ 27 | @Override 28 | public String getPageIndex(ListPage page) { 29 | int pageCount = page.getPageCount(); 30 | int curPage = page.getCurPage(); 31 | int recordCount = page.getRecordCount(); 32 | StringBuilder ret = new StringBuilder(); 33 | ret.append("

    "); 34 | if (pageCount >= 2) { 35 | Set set = new HashSet(); 36 | set.add(1); 37 | set.add(2); 38 | set.add(pageCount); 39 | set.add(curPage); 40 | if (curPage > 3) { 41 | set.add(curPage - 1); 42 | } 43 | if (curPage > 4) { 44 | set.add(curPage - 2); 45 | } 46 | if (curPage < pageCount - 2) { 47 | set.add(curPage + 1); 48 | } 49 | if (curPage < pageCount - 3) { 50 | set.add(curPage + 2); 51 | } 52 | if (pageCount > 3) { 53 | set.add(pageCount - 1); 54 | } 55 | List list = new ArrayList(set); 56 | Collections.sort(list); 57 | 58 | if (curPage > 1) { 59 | ret.append("
  • <
  • "); 60 | } else { 61 | ret.append("
  • <
  • "); 62 | } 63 | 64 | for (int i = 0; i < list.size(); i++) { 65 | int num = list.get(i); 66 | if (ret.length() > 0) { 67 | ret.append(" "); 68 | } 69 | if (i > 1 && list.get(i) - list.get(i - 1) > 1) { 70 | ret.append("
  • ...
  • "); 71 | } 72 | ret.append(renderSingleLink(num, curPage)); 73 | } 74 | 75 | if (curPage < pageCount) { 76 | ret.append("
  • >
  • "); 77 | } else { 78 | ret.append("
  • >
  • "); 79 | } 80 | } 81 | ret.append("
  • 共 ").append(recordCount).append(" 条记录
  • "); 82 | ret.append("
"); 83 | ret.append(getScript()); 84 | return ret.toString(); 85 | } 86 | 87 | /** 88 | * 得到单个翻页显示的HTML代码 89 | * 90 | * @param num 91 | * 显示的跳转页数 92 | * @param curPage 93 | * 当前页 94 | * @return HTML 95 | */ 96 | private String renderSingleLink(int num, int curPage) { 97 | StringBuilder sb = new StringBuilder(); 98 | if (num == curPage) { 99 | sb.append("
  • ").append(num).append("
  • "); 100 | } else { 101 | sb.append("
  • ").append(num).append("
  • "); 102 | } 103 | return sb.toString(); 104 | } 105 | 106 | /** 107 | * 得到翻页script脚本 108 | * 109 | * @return script脚本 110 | */ 111 | private String getScript() { 112 | StringBuilder sb = new StringBuilder(); 113 | sb.append(""); 115 | return sb.toString(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/wrappers/StringTrimmedResultSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.wrappers; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.sql.ResultSet; 9 | 10 | import com.opensource.dbhelp.dbutils.ProxyFactory; 11 | 12 | /** 13 | * Wraps a ResultSet to trim strings returned by the getString() and getObject() methods. 14 | *

    15 | * Usage Example: This example shows how to decorate ResultSets so processing continues as normal but all Strings are trimmed before being returned from the ResultSet. 16 | *

    17 | * 18 | *
    19 |  * 
    20 |  * ResultSet rs = // somehow get a ResultSet;
    21 |  * 
    22 |  * // Substitute wrapped ResultSet with additional behavior for real ResultSet
    23 |  * rs = StringTrimmedResultSet.wrap(rs);
    24 |  * 
    25 |  * // Pass wrapped ResultSet to processor
    26 |  * List list = new BasicRowProcessor().toBeanList(rs);
    27 |  * 
    28 | */ 29 | public class StringTrimmedResultSet implements InvocationHandler { 30 | 31 | /** 32 | * The factory to create proxies with. 33 | */ 34 | private static final ProxyFactory factory = ProxyFactory.instance(); 35 | 36 | /** 37 | * Wraps the ResultSet in an instance of this class. This is equivalent to: 38 | * 39 | *
    40 | 	 * ProxyFactory.instance().createResultSet(new StringTrimmedResultSet(rs));
    41 | 	 * 
    42 | * 43 | * @param rs 44 | * The ResultSet to wrap. 45 | * @return wrapped ResultSet 46 | */ 47 | public static ResultSet wrap(ResultSet rs) { 48 | return factory.createResultSet(new StringTrimmedResultSet(rs)); 49 | } 50 | 51 | /** 52 | * The wrapped result. 53 | */ 54 | private final ResultSet rs; 55 | 56 | /** 57 | * Constructs a new instance of StringTrimmedResultSet to wrap the specified ResultSet. 58 | * 59 | * @param rs 60 | * ResultSet to wrap 61 | */ 62 | public StringTrimmedResultSet(ResultSet rs) { 63 | super(); 64 | this.rs = rs; 65 | } 66 | 67 | /** 68 | * Intercept calls to the getString() and getObject() methods and trim any Strings before they're returned. 69 | * 70 | * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[]) 71 | * @param proxy 72 | * Not used; all method calls go to the internal result set 73 | * @param method 74 | * The method to invoke on the result set 75 | * @param args 76 | * The arguments to pass to the result set 77 | * @return string trimmed result 78 | * @throws Throwable 79 | * error 80 | */ 81 | @Override 82 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 83 | 84 | Object result = method.invoke(this.rs, args); 85 | 86 | if ((method.getName().equals("getObject") || method.getName().equals("getString")) && result instanceof String) { 87 | result = ((String) result).trim(); 88 | } 89 | 90 | return result; 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/ColumnListHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * ResultSetHandler implementation that converts one ResultSet column into a List of Objects. This class is thread safe. 11 | * 12 | * @param 13 | * The type of the column. 14 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 15 | * @since DbUtils 1.1 16 | */ 17 | public class ColumnListHandler extends AbstractListHandler { 18 | 19 | /** 20 | * The column number to retrieve. 21 | */ 22 | private final int columnIndex; 23 | 24 | /** 25 | * The column name to retrieve. Either columnName or columnIndex will be used but never both. 26 | */ 27 | private final String columnName; 28 | 29 | /** 30 | * Creates a new instance of ColumnListHandler. The first column of each row will be returned from handle(). 31 | */ 32 | public ColumnListHandler() { 33 | this(1, null); 34 | } 35 | 36 | /** 37 | * Creates a new instance of ColumnListHandler. 38 | * 39 | * @param columnIndex 40 | * The index of the column to retrieve from the ResultSet. 41 | */ 42 | public ColumnListHandler(int columnIndex) { 43 | this(columnIndex, null); 44 | } 45 | 46 | /** 47 | * Creates a new instance of ColumnListHandler. 48 | * 49 | * @param columnName 50 | * The name of the column to retrieve from the ResultSet. 51 | */ 52 | public ColumnListHandler(String columnName) { 53 | this(1, columnName); 54 | } 55 | 56 | /** 57 | * Private Helper 58 | * 59 | * @param columnIndex 60 | * The index of the column to retrieve from the ResultSet. 61 | * @param columnName 62 | * The name of the column to retrieve from the ResultSet. 63 | */ 64 | private ColumnListHandler(int columnIndex, String columnName) { 65 | super(); 66 | this.columnIndex = columnIndex; 67 | this.columnName = columnName; 68 | } 69 | 70 | /** 71 | * Returns one ResultSet column value as Object. 72 | * 73 | * @param rs 74 | * ResultSet to process. 75 | * @return Object, never null. 76 | * @throws java.sql.SQLException 77 | * if a database access error occurs 78 | * @throws ClassCastException 79 | * if the class datatype does not match the column type 80 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractListHandler#handle(java.sql.ResultSet) 81 | */ 82 | // We assume that the user has picked the correct type to match the column 83 | // so getObject will return the appropriate type and the cast will succeed. 84 | @SuppressWarnings("unchecked") 85 | @Override 86 | protected T handleRow(ResultSet rs) throws SQLException { 87 | if (this.columnName == null) { 88 | return (T) rs.getObject(this.columnIndex); 89 | } else { 90 | return (T) rs.getObject(this.columnName); 91 | } 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/RowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * RowProcessor implementations convert ResultSet rows into various other objects. Implementations can extend BasicRowProcessor to protect themselves from changes to this interface. 13 | * 14 | * @see BasicRowProcessor 15 | */ 16 | public interface RowProcessor { 17 | 18 | /** 19 | * Create an Object[] from the column values in one ResultSet row. The ResultSet should be positioned on a valid row before passing it to this method. Implementations of this method must not alter the row position of the ResultSet. 20 | * 21 | * @param rs 22 | * ResultSet that supplies the array data 23 | * @throws java.sql.SQLException 24 | * if a database access error occurs 25 | * @return the newly created array 26 | */ 27 | Object[] toArray(ResultSet rs) throws SQLException; 28 | 29 | /** 30 | * Create a JavaBean from the column values in one ResultSet row. The ResultSet should be positioned on a valid row before passing it to this method. Implementations of this method must not alter the row position of the ResultSet. 31 | * 32 | * @param 33 | * The type of bean to create 34 | * @param rs 35 | * ResultSet that supplies the bean data 36 | * @param type 37 | * Class from which to create the bean instance 38 | * @throws java.sql.SQLException 39 | * if a database access error occurs 40 | * @return the newly created bean 41 | */ 42 | T toBean(ResultSet rs, Class type) throws SQLException; 43 | 44 | /** 45 | * Create a List of JavaBeans from the column values in all ResultSet rows. ResultSet.next() should not be called before passing it to this method. 46 | * 47 | * @param 48 | * The type of bean to create 49 | * @param rs 50 | * ResultSet that supplies the bean data 51 | * @param type 52 | * Class from which to create the bean instance 53 | * @throws java.sql.SQLException 54 | * if a database access error occurs 55 | * @return A List of beans with the given type in the order they were returned by the ResultSet. 56 | */ 57 | List toBeanList(ResultSet rs, Class type) throws SQLException; 58 | 59 | /** 60 | * Create a Map from the column values in one ResultSet row. The ResultSet should be positioned on a valid row before passing it to this method. Implementations of this method must not alter the row position of the ResultSet. 61 | * 62 | * @param rs 63 | * ResultSet that supplies the map data 64 | * @throws java.sql.SQLException 65 | * if a database access error occurs 66 | * @return the newly created Map 67 | */ 68 | Map toMap(ResultSet rs) throws SQLException; 69 | 70 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/ScalarHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.ResultSetHandler; 10 | 11 | /** 12 | * ResultSetHandler implementation that converts one ResultSet column into an Object. This class is thread safe. 13 | * 14 | * @param 15 | * The type of the scalar 16 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 17 | */ 18 | public class ScalarHandler implements ResultSetHandler { 19 | 20 | /** 21 | * The column number to retrieve. 22 | */ 23 | private final int columnIndex; 24 | 25 | /** 26 | * The column name to retrieve. Either columnName or columnIndex will be used but never both. 27 | */ 28 | private final String columnName; 29 | 30 | /** 31 | * Creates a new instance of ScalarHandler. The first column will be returned from handle(). 32 | */ 33 | public ScalarHandler() { 34 | this(1, null); 35 | } 36 | 37 | /** 38 | * Creates a new instance of ScalarHandler. 39 | * 40 | * @param columnIndex 41 | * The index of the column to retrieve from the ResultSet. 42 | */ 43 | public ScalarHandler(int columnIndex) { 44 | this(columnIndex, null); 45 | } 46 | 47 | /** 48 | * Creates a new instance of ScalarHandler. 49 | * 50 | * @param columnName 51 | * The name of the column to retrieve from the ResultSet. 52 | */ 53 | public ScalarHandler(String columnName) { 54 | this(1, columnName); 55 | } 56 | 57 | /** 58 | * Helper constructor 59 | * 60 | * @param columnIndex 61 | * The index of the column to retrieve from the ResultSet. 62 | * @param columnName 63 | * The name of the column to retrieve from the ResultSet. 64 | */ 65 | private ScalarHandler(int columnIndex, String columnName) { 66 | this.columnIndex = columnIndex; 67 | this.columnName = columnName; 68 | } 69 | 70 | /** 71 | * Returns one ResultSet column as an object via the ResultSet.getObject() method that performs type conversions. 72 | * 73 | * @param rs 74 | * ResultSet to process. 75 | * @return The column or null if there are no rows in the ResultSet. 76 | * @throws java.sql.SQLException 77 | * if a database access error occurs 78 | * @throws ClassCastException 79 | * if the class datatype does not match the column type 80 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler#handle(java.sql.ResultSet) 81 | */ 82 | // We assume that the user has picked the correct type to match the column 83 | // so getObject will return the appropriate type and the cast will succeed. 84 | @SuppressWarnings("unchecked") 85 | @Override 86 | public T handle(ResultSet rs) throws SQLException { 87 | 88 | if (rs.next()) { 89 | if (this.columnName == null) { 90 | return (T) rs.getObject(this.columnIndex); 91 | } else { 92 | return (T) rs.getObject(this.columnName); 93 | } 94 | 95 | } else { 96 | return null; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/QueryLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Properties; 11 | 12 | /** 13 | * QueryLoader is a registry for sets of queries so that multiple copies of the same queries aren't loaded into memory. This implementation loads properties files filled with query name to SQL mappings. This class is thread safe. 14 | */ 15 | public class QueryLoader { 16 | 17 | /** 18 | * The Singleton instance of this class. 19 | */ 20 | private static final QueryLoader instance = new QueryLoader(); 21 | 22 | /** 23 | * Return an instance of this class. 24 | * 25 | * @return The Singleton instance. 26 | */ 27 | public static QueryLoader instance() { 28 | return instance; 29 | } 30 | 31 | /** 32 | * Maps query set names to Maps of their queries. 33 | */ 34 | private final Map> queries = new HashMap>(); 35 | 36 | /** 37 | * QueryLoader constructor. 38 | */ 39 | protected QueryLoader() { 40 | super(); 41 | } 42 | 43 | /** 44 | * Loads a Map of query names to SQL values. The Maps are cached so a subsequent request to load queries from the same path will return the cached Map. 45 | * 46 | * @param path 47 | * The path that the ClassLoader will use to find the file. This is not a file system path. If you had a jarred Queries.properties file in the com.yourcorp.app.jdbc package you would pass "/com/yourcorp/app/jdbc/Queries.properties" to this method. 48 | * @throws java.io.IOException 49 | * if a file access error occurs 50 | * @throws IllegalArgumentException 51 | * if the ClassLoader can't find a file at the given path. 52 | * @return Map of query names to SQL values 53 | */ 54 | public synchronized Map load(String path) throws IOException { 55 | 56 | Map queryMap = this.queries.get(path); 57 | 58 | if (queryMap == null) { 59 | queryMap = this.loadQueries(path); 60 | this.queries.put(path, queryMap); 61 | } 62 | 63 | return queryMap; 64 | } 65 | 66 | /** 67 | * Loads a set of named queries into a Map object. This implementation reads a properties file at the given path. 68 | * 69 | * @param path 70 | * The path that the ClassLoader will use to find the file. 71 | * @throws java.io.IOException 72 | * if a file access error occurs 73 | * @throws IllegalArgumentException 74 | * if the ClassLoader can't find a file at the given path. 75 | * @since DbUtils 1.1 76 | * @return Map of query names to SQL values 77 | */ 78 | protected Map loadQueries(String path) throws IOException { 79 | // Findbugs flags getClass().getResource as a bad practice; maybe we should change the API? 80 | InputStream in = getClass().getResourceAsStream(path); 81 | 82 | if (in == null) { 83 | throw new IllegalArgumentException(path + " not found."); 84 | } 85 | 86 | Properties props = new Properties(); 87 | try { 88 | props.load(in); 89 | } 90 | finally { 91 | in.close(); 92 | } 93 | 94 | // Copy to HashMap for better performance 95 | 96 | @SuppressWarnings({ "rawtypes", "unchecked" }) 97 | // load() always creates entries 98 | HashMap hashMap = new HashMap(props); 99 | return hashMap; 100 | } 101 | 102 | /** 103 | * Removes the queries for the given path from the cache. 104 | * 105 | * @param path 106 | * The path that the queries were loaded from. 107 | */ 108 | public synchronized void unload(String path) { 109 | this.queries.remove(path); 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/ResultSetIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Iterator; 9 | 10 | /** 11 | *

    12 | * Wraps a ResultSet in an Iterator. This is useful when you want to present a non-database application layer with domain neutral data. 13 | *

    14 | *

    15 | * This implementation requires the ResultSet.isLast() method to be implemented. 16 | *

    17 | */ 18 | public class ResultSetIterator implements Iterator { 19 | 20 | /** 21 | * The wrapped ResultSet. 22 | */ 23 | private final ResultSet rs; 24 | 25 | /** 26 | * The processor to use when converting a row into an Object[]. 27 | */ 28 | private final RowProcessor convert; 29 | 30 | /** 31 | * Constructor for ResultSetIterator. 32 | * 33 | * @param rs 34 | * Wrap this ResultSet in an Iterator. 35 | */ 36 | public ResultSetIterator(ResultSet rs) { 37 | this(rs, new BasicRowProcessor()); 38 | } 39 | 40 | /** 41 | * Constructor for ResultSetIterator. 42 | * 43 | * @param rs 44 | * Wrap this ResultSet in an Iterator. 45 | * @param convert 46 | * The processor to use when converting a row into an Object[]. Defaults to a BasicRowProcessor. 47 | */ 48 | public ResultSetIterator(ResultSet rs, RowProcessor convert) { 49 | this.rs = rs; 50 | this.convert = convert; 51 | } 52 | 53 | /** 54 | * Returns true if there are more rows in the ResultSet. 55 | * 56 | * @return boolean true if there are more rows 57 | * @throws RuntimeException 58 | * if an SQLException occurs. 59 | */ 60 | @Override 61 | public boolean hasNext() { 62 | try { 63 | return !rs.isLast(); 64 | } 65 | catch (SQLException e) { 66 | rethrow(e); 67 | return false; 68 | } 69 | } 70 | 71 | /** 72 | * Returns the next row as an Object[]. 73 | * 74 | * @return An Object[] with the same number of elements as columns in the ResultSet. 75 | * @see java.util.Iterator#next() 76 | * @throws RuntimeException 77 | * if an SQLException occurs. 78 | */ 79 | @Override 80 | public Object[] next() { 81 | try { 82 | rs.next(); 83 | return this.convert.toArray(rs); 84 | } 85 | catch (SQLException e) { 86 | rethrow(e); 87 | return null; 88 | } 89 | } 90 | 91 | /** 92 | * Deletes the current row from the ResultSet. 93 | * 94 | * @see java.util.Iterator#remove() 95 | * @throws RuntimeException 96 | * if an SQLException occurs. 97 | */ 98 | @Override 99 | public void remove() { 100 | try { 101 | this.rs.deleteRow(); 102 | } 103 | catch (SQLException e) { 104 | rethrow(e); 105 | } 106 | } 107 | 108 | /** 109 | * Rethrow the SQLException as a RuntimeException. This implementation creates a new RuntimeException with the SQLException's error message. 110 | * 111 | * @param e 112 | * SQLException to rethrow 113 | * @since DbUtils 1.1 114 | */ 115 | protected void rethrow(SQLException e) { 116 | throw new RuntimeException(e.getMessage()); 117 | } 118 | 119 | /** 120 | * Generates an Iterable, suitable for use in for-each loops. 121 | * 122 | * @param rs 123 | * Wrap this ResultSet in an Iterator. 124 | * @return an Iterable, suitable for use in for-each loops. 125 | */ 126 | public static Iterable iterable(final ResultSet rs) { 127 | return new Iterable() { 128 | 129 | @Override 130 | public Iterator iterator() { 131 | return new ResultSetIterator(rs); 132 | } 133 | 134 | }; 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Proxy; 8 | import java.sql.CallableStatement; 9 | import java.sql.Connection; 10 | import java.sql.Driver; 11 | import java.sql.PreparedStatement; 12 | import java.sql.ResultSet; 13 | import java.sql.ResultSetMetaData; 14 | import java.sql.Statement; 15 | 16 | /** 17 | * Creates proxy implementations of JDBC interfaces. This avoids incompatibilities between the JDBC 2 and JDBC 3 interfaces. This class is thread safe. 18 | * 19 | * @see java.lang.reflect.Proxy 20 | * @see java.lang.reflect.InvocationHandler 21 | */ 22 | public class ProxyFactory { 23 | 24 | /** 25 | * The Singleton instance of this class. 26 | */ 27 | private static final ProxyFactory instance = new ProxyFactory(); 28 | 29 | /** 30 | * Returns the Singleton instance of this class. 31 | * 32 | * @return singleton instance 33 | */ 34 | public static ProxyFactory instance() { 35 | return instance; 36 | } 37 | 38 | /** 39 | * Protected constructor for ProxyFactory subclasses to use. 40 | */ 41 | protected ProxyFactory() { 42 | super(); 43 | } 44 | 45 | /** 46 | * Convenience method to generate a single-interface proxy using the handler's classloader 47 | * 48 | * @param 49 | * The type of object to proxy 50 | * @param type 51 | * The type of object to proxy 52 | * @param handler 53 | * The handler that intercepts/overrides method calls. 54 | * @return proxied object 55 | */ 56 | public T newProxyInstance(Class type, InvocationHandler handler) { 57 | return type.cast(Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[] { type }, handler)); 58 | } 59 | 60 | /** 61 | * Creates a new proxy CallableStatement object. 62 | * 63 | * @param handler 64 | * The handler that intercepts/overrides method calls. 65 | * @return proxied CallableStatement 66 | */ 67 | public CallableStatement createCallableStatement(InvocationHandler handler) { 68 | return newProxyInstance(CallableStatement.class, handler); 69 | } 70 | 71 | /** 72 | * Creates a new proxy Connection object. 73 | * 74 | * @param handler 75 | * The handler that intercepts/overrides method calls. 76 | * @return proxied Connection 77 | */ 78 | public Connection createConnection(InvocationHandler handler) { 79 | return newProxyInstance(Connection.class, handler); 80 | } 81 | 82 | /** 83 | * Creates a new proxy Driver object. 84 | * 85 | * @param handler 86 | * The handler that intercepts/overrides method calls. 87 | * @return proxied Driver 88 | */ 89 | public Driver createDriver(InvocationHandler handler) { 90 | return newProxyInstance(Driver.class, handler); 91 | } 92 | 93 | /** 94 | * Creates a new proxy PreparedStatement object. 95 | * 96 | * @param handler 97 | * The handler that intercepts/overrides method calls. 98 | * @return proxied PreparedStatement 99 | */ 100 | public PreparedStatement createPreparedStatement(InvocationHandler handler) { 101 | return newProxyInstance(PreparedStatement.class, handler); 102 | } 103 | 104 | /** 105 | * Creates a new proxy ResultSet object. 106 | * 107 | * @param handler 108 | * The handler that intercepts/overrides method calls. 109 | * @return proxied ResultSet 110 | */ 111 | public ResultSet createResultSet(InvocationHandler handler) { 112 | return newProxyInstance(ResultSet.class, handler); 113 | } 114 | 115 | /** 116 | * Creates a new proxy ResultSetMetaData object. 117 | * 118 | * @param handler 119 | * The handler that intercepts/overrides method calls. 120 | * @return proxied ResultSetMetaData 121 | */ 122 | public ResultSetMetaData createResultSetMetaData(InvocationHandler handler) { 123 | return newProxyInstance(ResultSetMetaData.class, handler); 124 | } 125 | 126 | /** 127 | * Creates a new proxy Statement object. 128 | * 129 | * @param handler 130 | * The handler that intercepts/overrides method calls. 131 | * @return proxied Statement 132 | */ 133 | public Statement createStatement(InvocationHandler handler) { 134 | return newProxyInstance(Statement.class, handler); 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/Page.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 分页对象。 8 | *

    9 | * 用于包含数据及分页信息的对象
    10 | * Page类实现了用于显示分页信息的基本方法,但未指定所含数据的类型, 可根据需要实现以特定方式组织数据的子类,
    11 | * 如RowSetPage以RowSet封装数据,ListPage以List封装数据 12 | *

    13 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 14 | *

    15 | * Company: GNU General Public License 16 | *

    17 | * Author: GNU General Public License 18 | *

    19 | * Version: 1.0 20 | *

    21 | */ 22 | public class Page implements java.io.Serializable { 23 | 24 | /** sid */ 25 | private static final long serialVersionUID = -8901550401275849961L; 26 | 27 | /** 每页允许的最大记录数 */ 28 | public static final int MAX_PAGESIZE = Integer.MAX_VALUE; 29 | 30 | /** 空页对象 */ 31 | public static final Page EMPTY_PAGE = new Page(); 32 | 33 | /** 默认的每页记录数, 20 */ 34 | public static final int DEFAULT_PAGESIZE = 20; 35 | 36 | /** 每页记录数 */ 37 | private int myPageSize = DEFAULT_PAGESIZE; 38 | 39 | /*** 40 | * 本页数据在数据库中的起始位置 41 | */ 42 | private int start; 43 | 44 | /** 45 | * 本页包含的数据 46 | */ 47 | private List data; 48 | 49 | /** 50 | * 当前显示页 51 | */ 52 | private int curPage; 53 | 54 | /** 55 | * 本页包含的数据条数 56 | */ 57 | private int avaCount; 58 | 59 | /** 60 | * 页数 61 | */ 62 | private int pageCount; 63 | 64 | /** 65 | * 总记录数 66 | */ 67 | private int recordCount; 68 | 69 | /** 70 | * 默认构造方法,只构造空页 71 | */ 72 | protected Page() { 73 | this.init(0, 0, 0, DEFAULT_PAGESIZE, new ArrayList()); 74 | } 75 | 76 | /** 77 | * 分页数据初始方法,由子类调用 78 | * 79 | * @param start 80 | * 本页数据在数据库中的起始位置 81 | * @param avaCount 82 | * 本页包含的数据条数 83 | * @param totalSize 84 | * 数据库中总记录条数 85 | * @param pageSize 86 | * 本页容量 87 | * @param data 88 | * 本页包含的数据 89 | */ 90 | protected void init(int start, int avaCount, int totalSize, int pageSize, List data) { 91 | 92 | this.avaCount = avaCount; 93 | this.myPageSize = pageSize; 94 | 95 | this.start = start; 96 | this.recordCount = totalSize; 97 | 98 | this.data = data; 99 | 100 | if (avaCount > totalSize) { 101 | // throw new RuntimeException("记录条数大于总条数?!"); 102 | } 103 | 104 | this.curPage = (start - 1) / pageSize + 1; 105 | this.pageCount = (totalSize + pageSize - 1) / pageSize; 106 | 107 | if (totalSize == 0 && avaCount == 0) { 108 | this.curPage = 1; 109 | this.pageCount = 1; 110 | } 111 | } 112 | 113 | /** 114 | * 获得本页数据 115 | * 116 | * @return 本页数据 117 | */ 118 | public List getData() { 119 | return this.data; 120 | } 121 | 122 | /** 123 | * 取本页数据容量(本页能包含的记录数) 124 | * 125 | * @return 本页能包含的记录数 126 | */ 127 | public int getPageSize() { 128 | return this.myPageSize; 129 | } 130 | 131 | /** 132 | * 是否有下一页 133 | * 134 | * @return 是否有下一页 135 | */ 136 | public boolean hasNextPage() { 137 | return (this.getCurPage() < this.getPageCount()); 138 | } 139 | 140 | /** 141 | * 是否有上一页 142 | * 143 | * @return 是否有上一页 144 | */ 145 | public boolean hasPreviousPage() { 146 | return (this.getCurPage() > 1); 147 | } 148 | 149 | /** 150 | * 获取当前页第一条数据在数据库中的位置 151 | * 152 | * @return 得到当页开始记录在记录集中位置 153 | */ 154 | public int getStart() { 155 | return start; 156 | } 157 | 158 | /** 159 | * 获取当前页最后一条数据在数据库中的位置 160 | * 161 | * @return 得到当页结束记录在记录集中位置 162 | */ 163 | public int getEnd() { 164 | int end = this.getStart() + this.getAvaCount() - 1; 165 | if (end < 0) { 166 | end = 0; 167 | } 168 | return end; 169 | } 170 | 171 | /** 172 | * 获取上一页第一条数据在数据库中的位置 173 | * 174 | * @return 记录对应的rownum 175 | */ 176 | public int getStartOfPreviousPage() { 177 | return Math.max(start - myPageSize, 1); 178 | } 179 | 180 | /** 181 | * 获取下一页第一条数据在数据库中的位置 182 | * 183 | * @return 记录对应的rownum 184 | */ 185 | public int getStartOfNextPage() { 186 | return start + avaCount; 187 | } 188 | 189 | /** 190 | * 获取任一页第一条数据在数据库中的位置,每页条数使用默认值 191 | * 192 | * @param pageNo 193 | * 页号 194 | * @return 记录对应的rownum 195 | */ 196 | public static int getStartOfAnyPage(int pageNo) { 197 | return getStartOfAnyPage(pageNo, DEFAULT_PAGESIZE); 198 | } 199 | 200 | /** 201 | * 获取任一页第一条数据在数据库中的位置 202 | * 203 | * @param pageNo 204 | * 页号 205 | * @param pageSize 206 | * 每页包含的记录数 207 | * @return 记录对应的rownum 208 | */ 209 | public static int getStartOfAnyPage(int pageNo, int pageSize) { 210 | int startIndex = (pageNo - 1) * pageSize + 1; 211 | if (startIndex < 1) 212 | startIndex = 1; 213 | return startIndex; 214 | } 215 | 216 | /** 217 | * 取本页包含的记录数 218 | * 219 | * @return 本页包含的记录数 220 | */ 221 | public int getAvaCount() { 222 | return avaCount; 223 | } 224 | 225 | /** 226 | * 取数据库中包含的总记录数 227 | * 228 | * @return 数据库中包含的总记录数 229 | */ 230 | public int getRecordCount() { 231 | return this.recordCount; 232 | } 233 | 234 | /** 235 | * 取当前页码 236 | * 237 | * @return 当前页码 238 | */ 239 | public int getCurPage() { 240 | return this.curPage; 241 | } 242 | 243 | /** 244 | * 取总页码 245 | * 246 | * @return 总页码 247 | */ 248 | public int getPageCount() { 249 | return this.pageCount; 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/page/ListPagedStatement.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp.page; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import org.apache.commons.lang3.ArrayUtils; 9 | import org.apache.commons.logging.Log; 10 | import org.apache.commons.logging.LogFactory; 11 | 12 | import com.opensource.dbhelp.DbHelper; 13 | import com.opensource.dbhelp.dbutils.QueryRunner; 14 | import com.opensource.dbhelp.dbutils.handlers.BeanListHandler; 15 | import com.opensource.dbhelp.dbutils.handlers.MapListHandler; 16 | import com.opensource.dbhelp.dbutils.handlers.StringArrayHandler; 17 | import com.opensource.dbhelp.dbutils.handlers.StringArrayListHandler; 18 | import com.opensource.dbhelp.dbutils.handlers.StringMapListHandler; 19 | 20 | /** 21 | * 分页查询。 22 | *

    23 | * 根据查询语句和页码查询出当页数据。 24 | *

    25 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 26 | *

    27 | * Company: GNU General Public License 28 | *

    29 | * Author: GNU General Public License 30 | *

    31 | * Version: 1.0 32 | *

    33 | */ 34 | public class ListPagedStatement extends AbstractPagedStatement { 35 | 36 | /** logger */ 37 | private static final Log pagesqllogger = LogFactory.getLog("com.opensource.SQL.page"); 38 | 39 | /** 参数 */ 40 | protected Object[] params = new Object[] {}; 41 | 42 | /** Bean类 */ 43 | protected Class clazz = null; 44 | 45 | /** 查询结果对象 */ 46 | protected List list; 47 | 48 | /** 查询结果对象 */ 49 | protected ListPage listPage; 50 | 51 | /** 数据源 */ 52 | private DataSource dataSource; 53 | 54 | /** 55 | * 构造一查询出当页数据的PageStatement,并指定每页显示记录条数 56 | * 57 | * @param sql 58 | * query sql 59 | * @param params 60 | * 查询参数数组 61 | * @param pageNo 62 | * 页码 63 | * @param pageSize 64 | * 每页容量 65 | */ 66 | public ListPagedStatement(DataSource dataSource, String dialect, String sql, int pageNo, int pageSize, Object... params) { 67 | super(dialect, sql, pageNo, pageSize); 68 | if (params != null) { 69 | this.params = params; 70 | } 71 | this.dataSource = dataSource; 72 | } 73 | 74 | /** 75 | * 执行查询取得一页数据,执行结束后关闭数据库连接 76 | * 77 | * @return ListPage 78 | * @throws SQLException 79 | */ 80 | @Override 81 | @SuppressWarnings(value = "unchecked") 82 | public com.opensource.dbhelp.page.ListPage executeQuery(int type) throws SQLException { 83 | this.debug(0); 84 | 85 | QueryRunner run = new QueryRunner(dataSource); 86 | String[] count = run.query(this.countSql, new StringArrayHandler(), params); 87 | if (count != null) { 88 | totalCount = Integer.valueOf(count[0]); 89 | } else { 90 | totalCount = 0; 91 | } 92 | if (totalCount < 1) { 93 | 94 | return new ListPage(); 95 | } 96 | 97 | // set currentPage not greater than MaxPage 98 | // double maxPage = Math.ceil(Double.valueOf(this.totalCount)/Double.valueOf(this.pageSize)); 99 | // if (this.currentPage>maxPage) this.currentPage = Double.valueOf(maxPage).intValue(); 100 | 101 | params = pageSqlParser.attachPageParam(params, this.hasOffset, this.startIndex, this.pageSize); 102 | 103 | this.debug(1); 104 | 105 | if (clazz == null) { 106 | switch (type) { 107 | case 0: // return List 108 | this.list = (List) run.query(this.querySql, new StringArrayListHandler(), params); 109 | break; 110 | case 1: // return List> 111 | this.list = (List) run.query(this.querySql, new StringMapListHandler(), params); 112 | break; 113 | default: // return List> 114 | this.list = (List) run.query(this.querySql, new MapListHandler(), params); 115 | break; 116 | } 117 | } else { 118 | this.list = run.query(this.querySql, new BeanListHandler(clazz, DbHelper.BEAN_ROW_PROCESSOR), params); 119 | } 120 | 121 | this.listPage = new ListPage(this.list, startIndex, totalCount, pageSize); 122 | return this.listPage; 123 | } 124 | 125 | /** 126 | * 添加参数 127 | * 128 | * @param param 129 | * 单个参数 130 | */ 131 | public void addParam(Object param) { 132 | this.params = ArrayUtils.add(this.params, param); 133 | } 134 | 135 | /** 136 | * 添加参数 137 | * 138 | * @param params 139 | * 参数数组 140 | */ 141 | public void addParam(Object[] params) { 142 | this.params = ArrayUtils.addAll(this.params, params); 143 | } 144 | 145 | /** 146 | * 设置bean转化结果类 147 | * 148 | * @param clazz 149 | * bean类 150 | */ 151 | public void setClazz(Class clazz) { 152 | this.clazz = clazz; 153 | } 154 | 155 | /** 156 | * 取封装成List查询结果 157 | * 158 | * @return List 159 | */ 160 | public List getList() { 161 | return this.list; 162 | } 163 | 164 | /** 165 | * 取封装成ListPage的查询结果 166 | * 167 | * @return ListPage 168 | */ 169 | public com.opensource.dbhelp.page.ListPage getListPage() { 170 | return this.listPage; 171 | } 172 | 173 | /*** 174 | * 输出sql调试信息 175 | * 176 | * @param type 177 | * SQL类型 178 | */ 179 | private void debug(int type) { 180 | if (pagesqllogger.isDebugEnabled()) { 181 | StringBuilder sb = new StringBuilder(400); 182 | switch (type) { 183 | case 0: // countSql 184 | sb.append(this.countSql); 185 | if (params != null && params.length > 0) { 186 | sb.append(" [params:"); 187 | for (Object obj : params) { 188 | sb.append(obj == null ? "" : obj.toString()).append(", "); 189 | } 190 | sb.setLength(sb.length() - 2); 191 | sb.append("]"); 192 | } 193 | break; 194 | default: // pageSql 195 | sb.append(this.querySql); 196 | if (params != null && params.length > 0) { 197 | sb.append(" [params:"); 198 | for (Object obj : params) { 199 | sb.append(obj == null ? "" : obj.toString()).append(", "); 200 | } 201 | sb.setLength(sb.length() - 2); 202 | sb.append("]"); 203 | } 204 | sb.append(" [totalCount:").append(totalCount).append("]"); 205 | sb.append(" [currentPage:").append(currentPage).append("]"); 206 | sb.append(" [pageSize:").append(pageSize).append("]"); 207 | break; 208 | } 209 | pagesqllogger.debug(sb.toString()); 210 | } 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/KeyedHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Map; 9 | 10 | import com.opensource.dbhelp.dbutils.RowProcessor; 11 | 12 | /** 13 | *

    14 | * ResultSetHandler implementation that returns a Map of Maps. ResultSet rows are converted into Maps which are then stored in a Map under the given key. 15 | *

    16 | *

    17 | * If you had a Person table with a primary key column called ID, you could retrieve rows from the table like this: 18 | * 19 | *

     20 |  * 
     21 |  * ResultSetHandler h = new KeyedHandler("id");
     22 |  * 
     23 |  * Map found = (Map) queryRunner.query("select id, name, age from person", h);
     24 |  * 
     25 |  * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
     26 |  * 
     27 |  * String janesName = (String) jane.get("name");
     28 |  * 
     29 |  * Integer janesAge = (Integer) jane.get("age");
     30 |  * 
    31 | * 32 | * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the returned Map's get() method can be in any case. The data types returned for name and age are dependent upon how your JDBC driver converts SQL column types from the Person table into Java types. 33 | *

    34 | *

    35 | * This class is thread safe. 36 | *

    37 | * 38 | * @param 39 | * The type of the key 40 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 41 | * @since DbUtils 1.1 42 | */ 43 | public class KeyedHandler extends AbstractKeyedHandler> { 44 | 45 | /** 46 | * The RowProcessor implementation to use when converting rows into Objects. 47 | */ 48 | protected final RowProcessor convert; 49 | 50 | /** 51 | * The column index to retrieve key values from. Defaults to 1. 52 | */ 53 | protected final int columnIndex; 54 | 55 | /** 56 | * The column name to retrieve key values from. Either columnName or columnIndex will be used but never both. 57 | */ 58 | protected final String columnName; 59 | 60 | /** 61 | * Creates a new instance of KeyedHandler. The value of the first column of each row will be a key in the Map. 62 | */ 63 | public KeyedHandler() { 64 | this(ArrayHandler.ROW_PROCESSOR, 1, null); 65 | } 66 | 67 | /** 68 | * Creates a new instance of KeyedHandler. The value of the first column of each row will be a key in the Map. 69 | * 70 | * @param convert 71 | * The RowProcessor implementation to use when converting rows into Maps 72 | */ 73 | public KeyedHandler(RowProcessor convert) { 74 | this(convert, 1, null); 75 | } 76 | 77 | /** 78 | * Creates a new instance of KeyedHandler. 79 | * 80 | * @param columnIndex 81 | * The values to use as keys in the Map are retrieved from the column at this index. 82 | */ 83 | public KeyedHandler(int columnIndex) { 84 | this(ArrayHandler.ROW_PROCESSOR, columnIndex, null); 85 | } 86 | 87 | /** 88 | * Creates a new instance of KeyedHandler. 89 | * 90 | * @param columnName 91 | * The values to use as keys in the Map are retrieved from the column with this name. 92 | */ 93 | public KeyedHandler(String columnName) { 94 | this(ArrayHandler.ROW_PROCESSOR, 1, columnName); 95 | } 96 | 97 | /** 98 | * Private Helper 99 | * 100 | * @param convert 101 | * The RowProcessor implementation to use when converting rows into Maps 102 | * @param columnIndex 103 | * The values to use as keys in the Map are retrieved from the column at this index. 104 | * @param columnName 105 | * The values to use as keys in the Map are retrieved from the column with this name. 106 | */ 107 | private KeyedHandler(RowProcessor convert, int columnIndex, String columnName) { 108 | super(); 109 | this.convert = convert; 110 | this.columnIndex = columnIndex; 111 | this.columnName = columnName; 112 | } 113 | 114 | /** 115 | * This factory method is called by handle() to retrieve the key value from the current ResultSet row. This implementation returns ResultSet.getObject() for the configured key column name or index. 116 | * 117 | * @param rs 118 | * ResultSet to create a key from 119 | * @return Object from the configured key column name/index 120 | * @throws java.sql.SQLException 121 | * if a database access error occurs 122 | * @throws ClassCastException 123 | * if the class datatype does not match the column type 124 | */ 125 | // We assume that the user has picked the correct type to match the column 126 | // so getObject will return the appropriate type and the cast will succeed. 127 | @SuppressWarnings("unchecked") 128 | @Override 129 | protected K createKey(ResultSet rs) throws SQLException { 130 | return (columnName == null) ? (K) rs.getObject(columnIndex) : (K) rs.getObject(columnName); 131 | } 132 | 133 | /** 134 | * This factory method is called by handle() to store the current ResultSet row in some object. This implementation returns a Map with case insensitive column names as keys. Calls to map.get("COL") and map.get("col") return the same value. 135 | * 136 | * @param rs 137 | * ResultSet to create a row from 138 | * @return Object typed Map containing column names to values 139 | * @throws java.sql.SQLException 140 | * if a database access error occurs 141 | */ 142 | @Override 143 | protected Map createRow(ResultSet rs) throws SQLException { 144 | return this.convert.toMap(rs); 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/handlers/BeanMapHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.handlers; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | import com.opensource.dbhelp.dbutils.RowProcessor; 10 | 11 | /** 12 | *

    13 | * ResultSetHandler implementation that returns a Map of Beans. ResultSet rows are converted into Beans which are then stored in a Map under the given key. 14 | *

    15 | *

    16 | * If you had a Person table with a primary key column called ID, you could retrieve rows from the table like this: 17 | * 18 | *

     19 |  * ResultSetHandler<Map<Long, Person>> h = new BeanMapdHandler<Long, Person>(Person.class, "id");
     20 |  * Map&ltLong, Person> found = queryRunner.query("select id, name, age from person", h);
     21 |  * Person jane = found.get(1L); // jane's id is 1
     22 |  * String janesName = jane.getName();
     23 |  * Integer janesAge = jane.getAge();
     24 |  * 
    25 | * 26 | * Note that the "id" passed to BeanMapHandler can be in any case. The data type returned for id is dependent upon how your JDBC driver converts SQL column types from the Person table into Java types. The "name" and "age" columns are converted according to their property descriptors by DbUtils. 27 | *

    28 | *

    29 | * This class is thread safe. 30 | *

    31 | * 32 | * @param 33 | * the type of keys maintained by the returned map 34 | * @param 35 | * the type of the bean 36 | * @see com.opensource.dbhelp.dbutils.ResultSetHandler 37 | * @since DbUtils 1.5 38 | */ 39 | public class BeanMapHandler extends AbstractKeyedHandler { 40 | 41 | /** 42 | * The Class of beans produced by this handler. 43 | */ 44 | private final Class type; 45 | 46 | /** 47 | * The RowProcessor implementation to use when converting rows into Objects. 48 | */ 49 | private final RowProcessor convert; 50 | 51 | /** 52 | * The column index to retrieve key values from. Defaults to 1. 53 | */ 54 | private final int columnIndex; 55 | 56 | /** 57 | * The column name to retrieve key values from. Either columnName or columnIndex will be used but never both. 58 | */ 59 | private final String columnName; 60 | 61 | /** 62 | * Creates a new instance of BeanMapHandler. The value of the first column of each row will be a key in the Map. 63 | * 64 | * @param type 65 | * The Class that objects returned from createRow() are created from. 66 | */ 67 | public BeanMapHandler(Class type) { 68 | this(type, ArrayHandler.ROW_PROCESSOR, 1, null); 69 | } 70 | 71 | /** 72 | * Creates a new instance of BeanMapHandler. The value of the first column of each row will be a key in the Map. 73 | * 74 | * @param type 75 | * The Class that objects returned from createRow() are created from. 76 | * @param convert 77 | * The RowProcessor implementation to use when converting rows into Beans 78 | */ 79 | public BeanMapHandler(Class type, RowProcessor convert) { 80 | this(type, convert, 1, null); 81 | } 82 | 83 | /** 84 | * Creates a new instance of BeanMapHandler. 85 | * 86 | * @param type 87 | * The Class that objects returned from createRow() are created from. 88 | * @param columnIndex 89 | * The values to use as keys in the Map are retrieved from the column at this index. 90 | */ 91 | public BeanMapHandler(Class type, int columnIndex) { 92 | this(type, ArrayHandler.ROW_PROCESSOR, columnIndex, null); 93 | } 94 | 95 | /** 96 | * Creates a new instance of BeanMapHandler. 97 | * 98 | * @param type 99 | * The Class that objects returned from createRow() are created from. 100 | * @param columnName 101 | * The values to use as keys in the Map are retrieved from the column with this name. 102 | */ 103 | public BeanMapHandler(Class type, String columnName) { 104 | this(type, ArrayHandler.ROW_PROCESSOR, 1, columnName); 105 | } 106 | 107 | /** 108 | * Private Helper 109 | * 110 | * @param convert 111 | * The RowProcessor implementation to use when converting rows into Beans 112 | * @param columnIndex 113 | * The values to use as keys in the Map are retrieved from the column at this index. 114 | * @param columnName 115 | * The values to use as keys in the Map are retrieved from the column with this name. 116 | */ 117 | private BeanMapHandler(Class type, RowProcessor convert, int columnIndex, String columnName) { 118 | super(); 119 | this.type = type; 120 | this.convert = convert; 121 | this.columnIndex = columnIndex; 122 | this.columnName = columnName; 123 | } 124 | 125 | /** 126 | * This factory method is called by handle() to retrieve the key value from the current ResultSet row. 127 | * 128 | * @param rs 129 | * ResultSet to create a key from 130 | * @return K from the configured key column name/index 131 | * @throws java.sql.SQLException 132 | * if a database access error occurs 133 | * @throws ClassCastException 134 | * if the class datatype does not match the column type 135 | * @see com.opensource.dbhelp.dbutils.handlers.AbstractKeyedHandler#createKey(java.sql.ResultSet) 136 | */ 137 | // We assume that the user has picked the correct type to match the column 138 | // so getObject will return the appropriate type and the cast will succeed. 139 | @SuppressWarnings("unchecked") 140 | @Override 141 | protected K createKey(ResultSet rs) throws SQLException { 142 | return (columnName == null) ? (K) rs.getObject(columnIndex) : (K) rs.getObject(columnName); 143 | } 144 | 145 | @Override 146 | protected V createRow(ResultSet rs) throws SQLException { 147 | return this.convert.toBean(rs, type); 148 | } 149 | 150 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/BasicStringRowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.ResultSetMetaData; 8 | import java.sql.SQLException; 9 | import java.util.HashMap; 10 | import java.util.Locale; 11 | import java.util.Map; 12 | 13 | /** 14 | * Basic implementation of the StringRowProcessor interface. 15 | *

    16 | * This class is thread-safe. 17 | *

    18 | * 19 | * @see StringRowProcessor 20 | */ 21 | public class BasicStringRowProcessor implements StringRowProcessor { 22 | 23 | /** 24 | * The Singleton instance of this class. 25 | */ 26 | private static final BasicStringRowProcessor instance = new BasicStringRowProcessor(); 27 | 28 | /** 29 | * Returns the Singleton instance of this class. 30 | * 31 | * @return The single instance of this class. 32 | * @deprecated Create instances with the constructors instead. This will be removed after DbUtils 1.1. 33 | */ 34 | @Deprecated 35 | public static BasicStringRowProcessor instance() { 36 | return instance; 37 | } 38 | 39 | /** 40 | * BasicRowProcessor constructor. 41 | */ 42 | public BasicStringRowProcessor() { 43 | } 44 | 45 | /** 46 | * Convert a ResultSet row into an Object[]. This implementation copies column values into the array in the same order they're returned from the ResultSet. Array elements will be set to null if the column was SQL NULL. 47 | * 48 | * @see com.cplatform.dbhelp.dbutils.StringRowProcessor#toArray(java.sql.ResultSet) 49 | * @param rs 50 | * ResultSet that supplies the array data 51 | * @throws java.sql.SQLException 52 | * if a database access error occurs 53 | * @return the newly created array 54 | */ 55 | @Override 56 | public String[] toArray(ResultSet rs) throws SQLException { 57 | 58 | ResultSetMetaData meta = rs.getMetaData(); 59 | int cols = meta.getColumnCount(); 60 | String[] result = new String[cols]; 61 | 62 | for (int i = 0; i < cols; i++) { 63 | result[i] = trimToEmpty(rs.getString(i + 1)); 64 | } 65 | 66 | return result; 67 | } 68 | 69 | /** 70 | * Convert a ResultSet row into a Map. This implementation returns a Map with case insensitive column names as keys. Calls to map.get("COL") and map.get("col") return the same value. 71 | * 72 | * @see com.cplatform.dbhelp.dbutils.StringRowProcessor#toMap(java.sql.ResultSet) 73 | * @param rs 74 | * ResultSet that supplies the map data 75 | * @throws java.sql.SQLException 76 | * if a database access error occurs 77 | * @return the newly created Map 78 | */ 79 | @Override 80 | public Map toMap(ResultSet rs) throws SQLException { 81 | Map result = new CaseInsensitiveHashMap(); 82 | ResultSetMetaData rsmd = rs.getMetaData(); 83 | int cols = rsmd.getColumnCount(); 84 | 85 | for (int i = 1; i <= cols; i++) { 86 | result.put(rsmd.getColumnName(i), trimToEmpty(rs.getString(i))); 87 | } 88 | 89 | return result; 90 | } 91 | 92 | private static String trimToEmpty(String str) { 93 | return str != null ? str.trim() : ""; 94 | } 95 | 96 | /** 97 | * A Map that converts all keys to lowercase Strings for case insensitive lookups. This is needed for the toMap() implementation because databases don't consistently handle the casing of column names. 98 | *

    99 | * The keys are stored as they are given [BUG #DBUTILS-34], so we maintain an internal mapping from lowercase keys to the real keys in order to achieve the case insensitive lookup. 100 | *

    101 | * Note: This implementation does not allow null for key, whereas {@link java.util.HashMap} does, because of the code: 102 | * 103 | *

    104 | 	 * key.toString().toLowerCase()
    105 | 	 * 
    106 | */ 107 | private static class CaseInsensitiveHashMap extends HashMap { 108 | 109 | /** 110 | * The internal mapping from lowercase keys to the real keys. 111 | *

    112 | * Any query operation using the key ({@link #get(Object)}, {@link #containsKey(Object)}) is done in three steps: 113 | *

      114 | *
    • convert the parameter key to lower case
    • 115 | *
    • get the actual key that corresponds to the lower case key
    • 116 | *
    • query the map with the actual key
    • 117 | *
    118 | *

    119 | */ 120 | private final Map lowerCaseMap = new HashMap(); 121 | 122 | /** 123 | * Required for serialization support. 124 | * 125 | * @see java.io.Serializable 126 | */ 127 | private static final long serialVersionUID = -2848101435296897392L; 128 | 129 | /** {@inheritDoc} */ 130 | @Override 131 | public boolean containsKey(Object key) { 132 | Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH)); 133 | return super.containsKey(realKey); 134 | // Possible optimisation here: 135 | // Since the lowerCaseMap contains a mapping for all the keys, 136 | // we could just do this: 137 | // return lowerCaseMap.containsKey(key.toString().toLowerCase()); 138 | } 139 | 140 | /** {@inheritDoc} */ 141 | @Override 142 | public String get(Object key) { 143 | Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH)); 144 | return super.get(realKey); 145 | } 146 | 147 | /** {@inheritDoc} */ 148 | @Override 149 | public String put(String key, String value) { 150 | /* 151 | * In order to keep the map and lowerCaseMap synchronized, we have to remove the old mapping before putting the new one. Indeed, oldKey and key are not necessaliry equals. (That's why we call super.remove(oldKey) and not just super.put(key, value)) 152 | */ 153 | Object oldKey = lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key); 154 | String oldValue = super.remove(oldKey); 155 | super.put(key, value); 156 | return oldValue; 157 | } 158 | 159 | /** {@inheritDoc} */ 160 | @Override 161 | public void putAll(Map m) { 162 | for (Map.Entry entry : m.entrySet()) { 163 | String key = entry.getKey(); 164 | String value = entry.getValue(); 165 | this.put(key, value); 166 | } 167 | } 168 | 169 | /** {@inheritDoc} */ 170 | @Override 171 | public String remove(Object key) { 172 | Object realKey = lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH)); 173 | return super.remove(realKey); 174 | } 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/BasicRowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.ResultSetMetaData; 8 | import java.sql.SQLException; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Locale; 12 | import java.util.Map; 13 | 14 | /** 15 | * Basic implementation of the RowProcessor interface. 16 | *

    17 | * This class is thread-safe. 18 | *

    19 | * 20 | * @see RowProcessor 21 | */ 22 | public class BasicRowProcessor implements RowProcessor { 23 | 24 | /** 25 | * The default BeanProcessor instance to use if not supplied in the constructor. 26 | */ 27 | private static final BeanProcessor defaultConvert = new BeanProcessor(); 28 | 29 | /** 30 | * The Singleton instance of this class. 31 | */ 32 | private static final BasicRowProcessor instance = new BasicRowProcessor(); 33 | 34 | /** 35 | * Returns the Singleton instance of this class. 36 | * 37 | * @return The single instance of this class. 38 | * @deprecated Create instances with the constructors instead. This will be removed after DbUtils 1.1. 39 | */ 40 | @Deprecated 41 | public static BasicRowProcessor instance() { 42 | return instance; 43 | } 44 | 45 | /** 46 | * Use this to process beans. 47 | */ 48 | private final BeanProcessor convert; 49 | 50 | /** 51 | * BasicRowProcessor constructor. Bean processing defaults to a BeanProcessor instance. 52 | */ 53 | public BasicRowProcessor() { 54 | this(defaultConvert); 55 | } 56 | 57 | /** 58 | * BasicRowProcessor constructor. 59 | * 60 | * @param convert 61 | * The BeanProcessor to use when converting columns to bean properties. 62 | * @since DbUtils 1.1 63 | */ 64 | public BasicRowProcessor(BeanProcessor convert) { 65 | super(); 66 | this.convert = convert; 67 | } 68 | 69 | /** 70 | * Convert a ResultSet row into an Object[]. This implementation copies column values into the array in the same order they're returned from the ResultSet. Array elements will be set to null if the column was SQL NULL. 71 | * 72 | * @see com.cplatform.dbhelp.dbutils.RowProcessor#toArray(java.sql.ResultSet) 73 | * @param rs 74 | * ResultSet that supplies the array data 75 | * @throws java.sql.SQLException 76 | * if a database access error occurs 77 | * @return the newly created array 78 | */ 79 | @Override 80 | public Object[] toArray(ResultSet rs) throws SQLException { 81 | ResultSetMetaData meta = rs.getMetaData(); 82 | int cols = meta.getColumnCount(); 83 | Object[] result = new Object[cols]; 84 | 85 | for (int i = 0; i < cols; i++) { 86 | result[i] = rs.getObject(i + 1); 87 | } 88 | 89 | return result; 90 | } 91 | 92 | /** 93 | * Convert a ResultSet row into a JavaBean. This implementation delegates to a BeanProcessor instance. 94 | * 95 | * @see com.cplatform.dbhelp.dbutils.RowProcessor#toBean(java.sql.ResultSet, Class) 96 | * @see com.cplatform.dbhelp.dbutils.BeanProcessor#toBean(java.sql.ResultSet, Class) 97 | * @param 98 | * The type of bean to create 99 | * @param rs 100 | * ResultSet that supplies the bean data 101 | * @param type 102 | * Class from which to create the bean instance 103 | * @throws java.sql.SQLException 104 | * if a database access error occurs 105 | * @return the newly created bean 106 | */ 107 | @Override 108 | public T toBean(ResultSet rs, Class type) throws SQLException { 109 | return this.convert.toBean(rs, type); 110 | } 111 | 112 | /** 113 | * Convert a ResultSet into a List of JavaBeans. This implementation delegates to a BeanProcessor instance. 114 | * 115 | * @see com.cplatform.dbhelp.dbutils.RowProcessor#toBeanList(java.sql.ResultSet, Class) 116 | * @see com.cplatform.dbhelp.dbutils.BeanProcessor#toBeanList(java.sql.ResultSet, Class) 117 | * @param 118 | * The type of bean to create 119 | * @param rs 120 | * ResultSet that supplies the bean data 121 | * @param type 122 | * Class from which to create the bean instance 123 | * @throws java.sql.SQLException 124 | * if a database access error occurs 125 | * @return A List of beans with the given type in the order they were returned by the ResultSet. 126 | */ 127 | @Override 128 | public List toBeanList(ResultSet rs, Class type) throws SQLException { 129 | return this.convert.toBeanList(rs, type); 130 | } 131 | 132 | /** 133 | * Convert a ResultSet row into a Map. This implementation returns a Map with case insensitive column names as keys. Calls to map.get("COL") and map.get("col") return the same value. 134 | * 135 | * @see com.cplatform.dbhelp.dbutils.RowProcessor#toMap(java.sql.ResultSet) 136 | * @param rs 137 | * ResultSet that supplies the map data 138 | * @throws java.sql.SQLException 139 | * if a database access error occurs 140 | * @return the newly created Map 141 | */ 142 | @Override 143 | public Map toMap(ResultSet rs) throws SQLException { 144 | Map result = new CaseInsensitiveHashMap(); 145 | ResultSetMetaData rsmd = rs.getMetaData(); 146 | int cols = rsmd.getColumnCount(); 147 | 148 | for (int i = 1; i <= cols; i++) { 149 | result.put(rsmd.getColumnName(i), rs.getObject(i)); 150 | } 151 | 152 | return result; 153 | } 154 | 155 | /** 156 | * A Map that converts all keys to lowercase Strings for case insensitive lookups. This is needed for the toMap() implementation because databases don't consistently handle the casing of column names. 157 | *

    158 | * The keys are stored as they are given [BUG #DBUTILS-34], so we maintain an internal mapping from lowercase keys to the real keys in order to achieve the case insensitive lookup. 159 | *

    160 | * Note: This implementation does not allow null for key, whereas {@link java.util.HashMap} does, because of the code: 161 | * 162 | *

    163 | 	 * key.toString().toLowerCase()
    164 | 	 * 
    165 | */ 166 | private static class CaseInsensitiveHashMap extends HashMap { 167 | 168 | /** 169 | * The internal mapping from lowercase keys to the real keys. 170 | *

    171 | * Any query operation using the key ({@link #get(Object)}, {@link #containsKey(Object)}) is done in three steps: 172 | *

      173 | *
    • convert the parameter key to lower case
    • 174 | *
    • get the actual key that corresponds to the lower case key
    • 175 | *
    • query the map with the actual key
    • 176 | *
    177 | *

    178 | */ 179 | private final Map lowerCaseMap = new HashMap(); 180 | 181 | /** 182 | * Required for serialization support. 183 | * 184 | * @see java.io.Serializable 185 | */ 186 | private static final long serialVersionUID = -2848100435296897392L; 187 | 188 | /** {@inheritDoc} */ 189 | @Override 190 | public boolean containsKey(Object key) { 191 | Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH)); 192 | return super.containsKey(realKey); 193 | // Possible optimisation here: 194 | // Since the lowerCaseMap contains a mapping for all the keys, 195 | // we could just do this: 196 | // return lowerCaseMap.containsKey(key.toString().toLowerCase()); 197 | } 198 | 199 | /** {@inheritDoc} */ 200 | @Override 201 | public Object get(Object key) { 202 | Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH)); 203 | return super.get(realKey); 204 | } 205 | 206 | /** {@inheritDoc} */ 207 | @Override 208 | public Object put(String key, Object value) { 209 | /* 210 | * In order to keep the map and lowerCaseMap synchronized, we have to remove the old mapping before putting the new one. Indeed, oldKey and key are not necessaliry equals. (That's why we call super.remove(oldKey) and not just super.put(key, value)) 211 | */ 212 | Object oldKey = lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key); 213 | Object oldValue = super.remove(oldKey); 214 | super.put(key, value); 215 | return oldValue; 216 | } 217 | 218 | /** {@inheritDoc} */ 219 | @Override 220 | public void putAll(Map m) { 221 | for (Map.Entry entry : m.entrySet()) { 222 | String key = entry.getKey(); 223 | Object value = entry.getValue(); 224 | this.put(key, value); 225 | } 226 | } 227 | 228 | /** {@inheritDoc} */ 229 | @Override 230 | public Object remove(Object key) { 231 | Object realKey = lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH)); 232 | return super.remove(realKey); 233 | } 234 | } 235 | 236 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/DbUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.io.PrintWriter; 7 | import java.sql.Connection; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.sql.Statement; 11 | 12 | /** 13 | * A collection of JDBC helper methods. This class is thread safe. 14 | */ 15 | public final class DbUtils { 16 | 17 | /** 18 | * Default constructor. Utility classes should not have a public or default constructor, but this one preserves retro-compatibility. 19 | * 20 | * @since 1.4 21 | */ 22 | public DbUtils() { 23 | // do nothing 24 | } 25 | 26 | /** 27 | * Close a Connection, avoid closing if null. 28 | * 29 | * @param conn 30 | * Connection to close. 31 | * @throws java.sql.SQLException 32 | * if a database access error occurs 33 | */ 34 | public static void close(Connection conn) throws SQLException { 35 | if (conn != null) { 36 | conn.close(); 37 | } 38 | } 39 | 40 | /** 41 | * Close a ResultSet, avoid closing if null. 42 | * 43 | * @param rs 44 | * ResultSet to close. 45 | * @throws java.sql.SQLException 46 | * if a database access error occurs 47 | */ 48 | public static void close(ResultSet rs) throws SQLException { 49 | if (rs != null) { 50 | rs.close(); 51 | } 52 | } 53 | 54 | /** 55 | * Close a Statement, avoid closing if null. 56 | * 57 | * @param stmt 58 | * Statement to close. 59 | * @throws java.sql.SQLException 60 | * if a database access error occurs 61 | */ 62 | public static void close(Statement stmt) throws SQLException { 63 | if (stmt != null) { 64 | stmt.close(); 65 | } 66 | } 67 | 68 | /** 69 | * Close a Connection, avoid closing if null and hide any SQLExceptions that occur. 70 | * 71 | * @param conn 72 | * Connection to close. 73 | */ 74 | public static void closeQuietly(Connection conn) { 75 | try { 76 | close(conn); 77 | } 78 | catch (SQLException e) { // NOPMD 79 | // quiet 80 | } 81 | } 82 | 83 | /** 84 | * Close a Connection, Statement and ResultSet. Avoid closing if null and hide any SQLExceptions that occur. 85 | * 86 | * @param conn 87 | * Connection to close. 88 | * @param stmt 89 | * Statement to close. 90 | * @param rs 91 | * ResultSet to close. 92 | */ 93 | public static void closeQuietly(Connection conn, Statement stmt, ResultSet rs) { 94 | 95 | try { 96 | closeQuietly(rs); 97 | } 98 | finally { 99 | try { 100 | closeQuietly(stmt); 101 | } 102 | finally { 103 | closeQuietly(conn); 104 | } 105 | } 106 | 107 | } 108 | 109 | /** 110 | * Close a ResultSet, avoid closing if null and hide any SQLExceptions that occur. 111 | * 112 | * @param rs 113 | * ResultSet to close. 114 | */ 115 | public static void closeQuietly(ResultSet rs) { 116 | try { 117 | close(rs); 118 | } 119 | catch (SQLException e) { // NOPMD 120 | // quiet 121 | } 122 | } 123 | 124 | /** 125 | * Close a Statement, avoid closing if null and hide any SQLExceptions that occur. 126 | * 127 | * @param stmt 128 | * Statement to close. 129 | */ 130 | public static void closeQuietly(Statement stmt) { 131 | try { 132 | close(stmt); 133 | } 134 | catch (SQLException e) { // NOPMD 135 | // quiet 136 | } 137 | } 138 | 139 | /** 140 | * Commits a Connection then closes it, avoid closing if null. 141 | * 142 | * @param conn 143 | * Connection to close. 144 | * @throws java.sql.SQLException 145 | * if a database access error occurs 146 | */ 147 | public static void commitAndClose(Connection conn) throws SQLException { 148 | if (conn != null) { 149 | try { 150 | conn.commit(); 151 | } 152 | finally { 153 | conn.close(); 154 | } 155 | } 156 | } 157 | 158 | /** 159 | * Commits a Connection then closes it, avoid closing if null and hide any SQLExceptions that occur. 160 | * 161 | * @param conn 162 | * Connection to close. 163 | */ 164 | public static void commitAndCloseQuietly(Connection conn) { 165 | try { 166 | commitAndClose(conn); 167 | } 168 | catch (SQLException e) { // NOPMD 169 | // quiet 170 | } 171 | } 172 | 173 | /** 174 | * Loads and registers a database driver class. If this succeeds, it returns true, else it returns false. 175 | * 176 | * @param driverClassName 177 | * of driver to load 178 | * @return boolean true if the driver was found, otherwise false 179 | */ 180 | public static boolean loadDriver(String driverClassName) { 181 | return loadDriver(DbUtils.class.getClassLoader(), driverClassName); 182 | } 183 | 184 | /** 185 | * Loads and registers a database driver class. If this succeeds, it returns true, else it returns false. 186 | * 187 | * @param classLoader 188 | * the class loader used to load the driver class 189 | * @param driverClassName 190 | * of driver to load 191 | * @return boolean true if the driver was found, otherwise false 192 | * @since 1.4 193 | */ 194 | public static boolean loadDriver(ClassLoader classLoader, String driverClassName) { 195 | try { 196 | classLoader.loadClass(driverClassName).newInstance(); 197 | return true; 198 | 199 | } 200 | catch (IllegalAccessException e) { 201 | // Constructor is private, OK for DriverManager contract 202 | return true; 203 | 204 | } 205 | catch (Exception e) { 206 | return false; 207 | 208 | } 209 | } 210 | 211 | /** 212 | * Print the stack trace for a SQLException to STDERR. 213 | * 214 | * @param e 215 | * SQLException to print stack trace of 216 | */ 217 | public static void printStackTrace(SQLException e) { 218 | printStackTrace(e, new PrintWriter(System.err)); 219 | } 220 | 221 | /** 222 | * Print the stack trace for a SQLException to a specified PrintWriter. 223 | * 224 | * @param e 225 | * SQLException to print stack trace of 226 | * @param pw 227 | * PrintWriter to print to 228 | */ 229 | public static void printStackTrace(SQLException e, PrintWriter pw) { 230 | 231 | SQLException next = e; 232 | while (next != null) { 233 | next.printStackTrace(pw); 234 | next = next.getNextException(); 235 | if (next != null) { 236 | pw.println("Next SQLException:"); 237 | } 238 | } 239 | } 240 | 241 | /** 242 | * Print warnings on a Connection to STDERR. 243 | * 244 | * @param conn 245 | * Connection to print warnings from 246 | */ 247 | public static void printWarnings(Connection conn) { 248 | printWarnings(conn, new PrintWriter(System.err)); 249 | } 250 | 251 | /** 252 | * Print warnings on a Connection to a specified PrintWriter. 253 | * 254 | * @param conn 255 | * Connection to print warnings from 256 | * @param pw 257 | * PrintWriter to print to 258 | */ 259 | public static void printWarnings(Connection conn, PrintWriter pw) { 260 | if (conn != null) { 261 | try { 262 | printStackTrace(conn.getWarnings(), pw); 263 | } 264 | catch (SQLException e) { 265 | printStackTrace(e, pw); 266 | } 267 | } 268 | } 269 | 270 | /** 271 | * Rollback any changes made on the given connection. 272 | * 273 | * @param conn 274 | * Connection to rollback. A null value is legal. 275 | * @throws java.sql.SQLException 276 | * if a database access error occurs 277 | */ 278 | public static void rollback(Connection conn) throws SQLException { 279 | if (conn != null) { 280 | conn.rollback(); 281 | } 282 | } 283 | 284 | /** 285 | * Performs a rollback on the Connection then closes it, avoid closing if null. 286 | * 287 | * @param conn 288 | * Connection to rollback. A null value is legal. 289 | * @throws java.sql.SQLException 290 | * if a database access error occurs 291 | * @since DbUtils 1.1 292 | */ 293 | public static void rollbackAndClose(Connection conn) throws SQLException { 294 | if (conn != null) { 295 | try { 296 | conn.rollback(); 297 | } 298 | finally { 299 | conn.close(); 300 | } 301 | } 302 | } 303 | 304 | /** 305 | * Performs a rollback on the Connection then closes it, avoid closing if null and hide any SQLExceptions that occur. 306 | * 307 | * @param conn 308 | * Connection to rollback. A null value is legal. 309 | * @since DbUtils 1.1 310 | */ 311 | public static void rollbackAndCloseQuietly(Connection conn) { 312 | try { 313 | rollbackAndClose(conn); 314 | } 315 | catch (SQLException e) { // NOPMD 316 | // quiet 317 | } 318 | } 319 | 320 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/DbTransaction.java: -------------------------------------------------------------------------------- 1 | package com.opensource.dbhelp; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | import java.util.List; 6 | 7 | import javax.sql.DataSource; 8 | 9 | import org.apache.commons.logging.Log; 10 | import org.apache.commons.logging.LogFactory; 11 | 12 | import com.opensource.dbhelp.dbutils.DbUtils; 13 | import com.opensource.dbhelp.dbutils.QueryRunner; 14 | import com.opensource.dbhelp.dbutils.handlers.BeanHandler; 15 | import com.opensource.dbhelp.dbutils.handlers.BeanListHandler; 16 | import com.opensource.dbhelp.dbutils.handlers.StringArrayHandler; 17 | import com.opensource.dbhelp.dbutils.handlers.StringArrayListHandler; 18 | 19 | /** 20 | * 数据库事务处理帮助类。 21 | *

    22 | * 典型的调用方法如下:
    23 | * 24 | *

     25 |  * DbTransaction dbc = DbHelperManager.getHelper().getDbTransaction();
     26 |  * try {
     27 |  *     dbc.connect();
     28 |  *     dbc.begin();
     29 |  * 
     30 |  *     dbc.execute("select ...", new Object[]{...});
     31 |  *     dbc.execute("insert into ...", ...);
     32 |  *     dbc.execute("insert into ...");
     33 |  * 
     34 |  *     String[] tmp1 = dbc.find("select ...", new Object[]{...});
     35 |  *     System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp1) );
     36 |  * 
     37 |  *     List params = new ArrayList();
     38 |  *     params.add(new Object[]{3213, "20080920101111"});
     39 |  *     params.add(new Object[]{3214, "20080920101111"});
     40 |  *     params.add(new Object[]{3215, "20080920101111"});
     41 |  * 
     42 |  *     dbc.batch("insert into ... values (?, ?)", params);
     43 |  * 
     44 |  *     List tmp2 = dbc.query("select * from ...");
     45 |  *     System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp2) );
     46 |  * 
     47 |  *     dbc.execute("delete from ...", new Object[]{...});
     48 |  * 
     49 |  *     dbc.commit();
     50 |  * } catch (Exception e) {
     51 |  *     dbc.rollback();
     52 |  *     throw e;
     53 |  * } finally {
     54 |  *     dbc.close();
     55 |  * }
     56 |  * 
    57 | *

    58 | * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM 59 | *

    60 | * Company: GNU General Public License 61 | *

    62 | * Author: GNU General Public License 63 | *

    64 | * Version: 1.0 65 | *

    66 | */ 67 | public class DbTransaction { 68 | 69 | /** 70 | * logger 71 | */ 72 | private static final Log logger = LogFactory.getLog(DbTransaction.class); 73 | 74 | /** 75 | * sql logger,用于把执行的SQL语句及参数进行单独记录 76 | */ 77 | private static final Log sqllogger = LogFactory.getLog("com.opensource.SQL"); 78 | 79 | /** 80 | * 数据库连接 81 | */ 82 | private Connection conn = null; 83 | 84 | /** 85 | * 是否自动提交 86 | */ 87 | private boolean isAutoCommit; 88 | 89 | /** 90 | * QueryRunner对象 91 | */ 92 | private QueryRunner run = null; 93 | 94 | /** 95 | * 初始化时初始化QueryRunner对象 96 | * 97 | * @param dataSource 98 | * 使用的数据源 99 | */ 100 | public DbTransaction(DataSource dataSource) { 101 | run = new QueryRunner(dataSource); 102 | } 103 | 104 | /** 105 | * 建立数据库连接 106 | * 107 | * @throws SQLException 108 | * - 如果不能建立连接 109 | */ 110 | public void connect() throws SQLException { 111 | try { 112 | conn = run.getDataSource().getConnection(); 113 | } 114 | catch (SQLException ex) { 115 | logger.error("get connection error!", ex); 116 | throw ex; 117 | } 118 | } 119 | 120 | /** 121 | * 事务生命周期开始 122 | * 123 | * @throws SQLException 124 | * SQL异常 125 | */ 126 | public void begin() throws SQLException { 127 | try { 128 | isAutoCommit = conn.getAutoCommit(); 129 | conn.setAutoCommit(false); 130 | } 131 | catch (SQLException ex) { 132 | logger.error("begin transaction error!", ex); 133 | throw ex; 134 | } 135 | } 136 | 137 | /** 138 | * 获取数据库连接 139 | * 140 | * @return 数据库连接对象 141 | */ 142 | public Connection getConnection() { 143 | return conn; 144 | } 145 | 146 | /** 147 | * 结束事务生命周期,提交所有变更 148 | * 149 | * @throws SQLException 150 | * SQL异常 151 | */ 152 | public void commit() throws SQLException { 153 | try { 154 | conn.commit(); 155 | conn.setAutoCommit(isAutoCommit); 156 | } 157 | catch (SQLException ex) { 158 | logger.error("commit transaction error!", ex); 159 | throw ex; 160 | } 161 | } 162 | 163 | /** 164 | * 事务回滚 165 | */ 166 | public void rollback() { 167 | try { 168 | conn.rollback(); 169 | conn.setAutoCommit(isAutoCommit); 170 | } 171 | catch (SQLException ex) { 172 | logger.error("rollback transaction error!", ex); 173 | } 174 | } 175 | 176 | /** 177 | * 判断是否为自动加入数据模式 178 | * 179 | * @return 是否为自动提交 180 | * @throws SQLException 181 | * SQL异常 182 | */ 183 | public boolean getAutoCommit() throws SQLException { 184 | boolean result; 185 | try { 186 | result = conn.getAutoCommit(); 187 | } 188 | catch (SQLException ex) { 189 | logger.error("get auto commit status error!", ex); 190 | throw ex; 191 | } 192 | return result; 193 | } 194 | 195 | /** 196 | * sql执行操作,用于数据更新,主要是Update,Insert,delete 197 | * 198 | * @param sql 199 | * 要执行的sql语句 200 | * @return 影响的行数 201 | * @throws SQLException 202 | * 捕捉错误 203 | */ 204 | public int execute(String sql) throws SQLException { 205 | return execute(sql, (Object[]) null); 206 | } 207 | 208 | /** 209 | * sql执行操作,用于数据更新,主要是Update,Insert,delete 210 | * 211 | * @param sql 212 | * 要执行的sql语句 213 | * @param param 214 | * 参数对象 215 | * @return 影响的行数 216 | * @throws SQLException 217 | * 捕捉错误 218 | */ 219 | public int execute(String sql, Object param) throws SQLException { 220 | return execute(sql, new Object[] { param }); 221 | } 222 | 223 | /** 224 | * sql执行操作,用于数据更新,主要是Update,Insert,delete 225 | * 226 | * @param sql 227 | * 要执行的sql语句 228 | * @param params 229 | * 参数数组对象 230 | * @return 影响的行数 231 | * @throws SQLException 232 | * 捕捉错误 233 | */ 234 | public int execute(String sql, Object... params) throws SQLException { 235 | debug(sql, params); 236 | return run.update(conn, sql, params); 237 | } 238 | 239 | /** 240 | * 批处理执行sql 241 | * 242 | * @param sql 243 | * 要执行的SQL语句 244 | * @param params 245 | * 参数数组对象 246 | * @return The number of rows updated per statement. 247 | * @throws SQLException 248 | * SQL异常 249 | */ 250 | public int[] batch(String sql, List params) throws SQLException { 251 | debug(sql, "batch sql, count:" + ((params == null) ? -1 : params.size())); 252 | assert params != null; 253 | Object[][] p = new Object[params.size()][]; 254 | for (int i = 0; i < params.size(); i++) { 255 | p[i] = params.get(i); 256 | } 257 | return run.batch(conn, sql, p); 258 | } 259 | 260 | /** 261 | * 查找单条记录 262 | * 263 | * @param sql 264 | * 要执行的SQL语句 265 | * @return 如果查询不到记录,返回null 266 | * @throws SQLException 267 | * SQL异常 268 | */ 269 | public String[] find(String sql) throws SQLException { 270 | return find(sql, (Object[]) null); 271 | } 272 | 273 | /** 274 | * 查找单条记录 275 | * 276 | * @param sql 277 | * 要执行的SQL语句 278 | * @param param 279 | * 参数对象 280 | * @return 如果查询不到记录,返回null 281 | * @throws SQLException 282 | * SQL异常 283 | */ 284 | public String[] find(String sql, Object param) throws SQLException { 285 | return find(sql, new Object[] { param }); 286 | } 287 | 288 | /** 289 | * 查找单条记录 290 | * 291 | * @param sql 292 | * 要执行的SQL语句 293 | * @param params 294 | * 参数数组 295 | * @return 如果查询不到记录,返回null 296 | * @throws SQLException 297 | * SQL异常 298 | */ 299 | public String[] find(String sql, Object... params) throws SQLException { 300 | debug(sql, params); 301 | return run.query(conn, sql, new StringArrayHandler(), params); 302 | } 303 | 304 | /** 305 | * 查找单条记录 306 | * 307 | * @param sql 308 | * 要执行的SQL语句 309 | * @param type 310 | * 指定类 311 | * @return 如果查询不到记录,返回null 312 | * @throws SQLException 313 | * SQL异常 314 | */ 315 | public T find(String sql, Class type) throws SQLException { 316 | return find(sql, type, (Object[]) null); 317 | } 318 | 319 | /** 320 | * 查找单条记录 321 | * 322 | * @param sql 323 | * 要执行的SQL语句 324 | * @param type 325 | * 指定类 326 | * @param param 327 | * 参数对象 328 | * @return 如果查询不到记录,返回null 329 | * @throws SQLException 330 | * SQL异常 331 | */ 332 | public T find(String sql, Class type, Object param) throws SQLException { 333 | return find(sql, type, new Object[] { param }); 334 | } 335 | 336 | /** 337 | * 查找单条记录 338 | * 339 | * @param sql 340 | * 要执行的SQL语句 341 | * @param type 342 | * 指定类 343 | * @param params 344 | * 参数数组 345 | * @return 如果查询不到记录,返回null 346 | * @throws SQLException 347 | * SQL异常 348 | */ 349 | public T find(String sql, Class type, Object... params) throws SQLException { 350 | debug(sql, params); 351 | return run.query(conn, sql, new BeanHandler(type, DbHelper.BEAN_ROW_PROCESSOR), params); 352 | } 353 | 354 | /** 355 | * 查询所有记录到list中 356 | * 357 | * @param sql 358 | * 要执行的SQL语句 359 | * @return 如果没有查询结果,返回容量为0的list 360 | * @throws SQLException 361 | * SQL异常 362 | */ 363 | public List query(String sql) throws SQLException { 364 | return query(sql, (Object[]) null); 365 | } 366 | 367 | /** 368 | * 查询所有记录到list中 369 | * 370 | * @param sql 371 | * 要执行的SQL语句 372 | * @param param 373 | * 参数对象 374 | * @return 如果没有查询结果,返回容量为0的list 375 | * @throws SQLException 376 | * SQL异常 377 | */ 378 | public List query(String sql, Object param) throws SQLException { 379 | return query(sql, new Object[] { param }); 380 | } 381 | 382 | /** 383 | * 查询所有记录到list中 384 | * 385 | * @param sql 386 | * 要执行的SQL语句 387 | * @param params 388 | * 参数数组对象 389 | * @return 如果没有查询结果,返回容量为0的list 390 | * @throws SQLException 391 | * SQL异常 392 | */ 393 | public List query(String sql, Object... params) throws SQLException { 394 | debug(sql, params); 395 | return run.query(conn, sql, new StringArrayListHandler(), params); 396 | } 397 | 398 | /** 399 | * 查询所有记录到bean list中 400 | * 401 | * @param sql 402 | * 要执行的SQL语句 403 | * @param type 404 | * 指定类 405 | * @return 如果没有查询结果,返回容量为0的list 406 | * @throws SQLException 407 | * SQL异常 408 | */ 409 | public List query(String sql, Class type) throws SQLException { 410 | return query(sql, type, (Object[]) null); 411 | } 412 | 413 | /** 414 | * 查询所有记录到bean list中 415 | * 416 | * @param sql 417 | * 要执行的SQL语句 418 | * @param type 419 | * 指定类 420 | * @param param 421 | * 参数对象 422 | * @return 如果没有查询结果,返回容量为0的list 423 | * @throws SQLException 424 | * SQL异常 425 | */ 426 | public List query(String sql, Class type, Object param) throws SQLException { 427 | return query(sql, type, new Object[] { param }); 428 | } 429 | 430 | /** 431 | * 查询所有记录到bean list中 432 | * 433 | * @param sql 434 | * 要执行的SQL语句 435 | * @param type 436 | * 指定类 437 | * @param params 438 | * 参数数组对象 439 | * @return 如果没有查询结果,返回容量为0的list 440 | * @throws SQLException 441 | * SQL异常 442 | */ 443 | public List query(String sql, Class type, Object... params) throws SQLException { 444 | debug(sql, params); 445 | return run.query(conn, sql, new BeanListHandler(type, DbHelper.BEAN_ROW_PROCESSOR), params); 446 | } 447 | 448 | /** 449 | * 关闭连接 450 | */ 451 | public void close() { 452 | DbUtils.closeQuietly(conn); 453 | conn = null; 454 | } 455 | 456 | /** 457 | * 输出debug信息 458 | * 459 | * @param sql 460 | * 执行的SQL语句 461 | * @param params 462 | * 执行的参数 463 | */ 464 | private static void debug(String sql, Object... params) { 465 | if (sqllogger.isDebugEnabled()) { 466 | if (params == null) { 467 | params = new Object[] {}; 468 | } 469 | StringBuilder sb = new StringBuilder(400); 470 | sb.append(sql); 471 | if (params.length != 0) { 472 | sb.append(" [params:"); 473 | for (Object obj : params) { 474 | sb.append(obj == null ? "" : obj.toString()).append(", "); 475 | } 476 | sb.setLength(sb.length() - 2); 477 | sb.append("]"); 478 | } 479 | sqllogger.debug(sb.toString()); 480 | } 481 | } 482 | 483 | /** 484 | * 内部测试方法。。。 485 | * 486 | * @param args 487 | * 参数 488 | * @throws Exception 489 | * 异常 490 | */ 491 | public static void main(String[] args) throws Exception { 492 | /* 493 | * DbTransaction dbc = new DbTransaction(); String[] tmp1; List tmp2; try { dbc.connect(); dbc.begin(); dbc.execute("insert into t_sns_session (user_id, last_activity) values (?, ?)", new Object[]{3210, "20080920101111"}); dbc.execute("insert into t_sns_session (user_id, last_activity) values (?, '20090102000000')", 3211); dbc.execute("insert into t_sns_session (user_id, last_activity) values (3212, '20090102000000')"); tmp1 = dbc.find("select * from t_sns_session where user_id=? and user_id=?", new Object[]{3210,3210}); System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp1) ); tmp1 = dbc.find("select * from t_sns_session where user_id=?", 3211); System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp1) ); tmp1 = dbc.find("select * from t_sns_session where user_id=3212"); 494 | * System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp1) ); tmp2 = dbc.query("select * from t_sns_session"); System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp2) ); List params = new ArrayList(); params.add(new Object[]{3213, "20080920101111"}); params.add(new Object[]{3214, "20080920101111"}); params.add(new Object[]{3215, "20080920101111"}); dbc.batch("insert into t_sns_session (user_id, last_activity) values (?, ?)", params); tmp2 = dbc.query("select * from t_sns_session"); System.out.println( org.apache.commons.lang.builder.ToStringBuilder.reflectionToString(tmp2) ); dbc.execute("delete from t_sns_session where user_id=? or user_id=?", new Object[]{3210, 3211}); dbc.execute("delete from t_sns_session where user_id=?", 3212); dbc.execute("delete from t_sns_session1"); 495 | * dbc.commit(); } catch (Exception e) { dbc.rollback(); throw e; } finally { dbc.close(); } 496 | */ 497 | } 498 | 499 | } 500 | -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/AbstractQueryRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.beans.IntrospectionException; 7 | import java.beans.Introspector; 8 | import java.beans.PropertyDescriptor; 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.lang.reflect.Method; 11 | import java.sql.Connection; 12 | import java.sql.ParameterMetaData; 13 | import java.sql.PreparedStatement; 14 | import java.sql.ResultSet; 15 | import java.sql.SQLException; 16 | import java.sql.Statement; 17 | import java.sql.Types; 18 | import java.util.Arrays; 19 | 20 | import javax.sql.DataSource; 21 | 22 | /** 23 | * The base class for QueryRunner & AsyncQueryRunner. This class is thread safe. 24 | * 25 | * @since 1.4 (mostly extracted from QueryRunner) 26 | */ 27 | public abstract class AbstractQueryRunner { 28 | 29 | /** 30 | * Is {@link java.sql.ParameterMetaData#getParameterType(int)} broken (have we tried it yet)? 31 | */ 32 | private volatile boolean pmdKnownBroken = false; 33 | 34 | /** 35 | * The DataSource to retrieve connections from. 36 | * 37 | * @deprecated Access to this field should be through {@link #getDataSource()}. 38 | */ 39 | @Deprecated 40 | protected final DataSource ds; 41 | 42 | /** 43 | * Default constructor, sets pmdKnownBroken to false and ds to null. 44 | */ 45 | public AbstractQueryRunner() { 46 | ds = null; 47 | } 48 | 49 | /** 50 | * Constructor to control the use of ParameterMetaData. 51 | * 52 | * @param pmdKnownBroken 53 | * Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) }; if pmdKnownBroken is set to true, we won't even try it; if false, we'll try it, and if it breaks, we'll remember not to use it again. 54 | */ 55 | public AbstractQueryRunner(boolean pmdKnownBroken) { 56 | this.pmdKnownBroken = pmdKnownBroken; 57 | ds = null; 58 | } 59 | 60 | /** 61 | * Constructor to provide a DataSource. Methods that do not take a Connection parameter will retrieve connections from this DataSource. 62 | * 63 | * @param ds 64 | * The DataSource to retrieve connections from. 65 | */ 66 | public AbstractQueryRunner(DataSource ds) { 67 | this.ds = ds; 68 | } 69 | 70 | /** 71 | * Constructor to provide a DataSource and control the use of ParameterMetaData. Methods that do not take a Connection parameter will retrieve connections from this DataSource. 72 | * 73 | * @param ds 74 | * The DataSource to retrieve connections from. 75 | * @param pmdKnownBroken 76 | * Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) }; if pmdKnownBroken is set to true, we won't even try it; if false, we'll try it, and if it breaks, we'll remember not to use it again. 77 | */ 78 | public AbstractQueryRunner(DataSource ds, boolean pmdKnownBroken) { 79 | this.pmdKnownBroken = pmdKnownBroken; 80 | this.ds = ds; 81 | } 82 | 83 | /** 84 | * Returns the DataSource this runner is using. QueryRunner methods always call this method to get the DataSource so subclasses can provide specialized behavior. 85 | * 86 | * @return DataSource the runner is using 87 | */ 88 | public DataSource getDataSource() { 89 | return this.ds; 90 | } 91 | 92 | /** 93 | * Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) }; if pmdKnownBroken is set to true, we won't even try it; if false, we'll try it, and if it breaks, we'll remember not to use it again. 94 | * 95 | * @return the flag to skip (or not) {@link java.sql.ParameterMetaData#getParameterType(int) } 96 | * @since 1.4 97 | */ 98 | public boolean isPmdKnownBroken() { 99 | return pmdKnownBroken; 100 | } 101 | 102 | /** 103 | * Factory method that creates and initializes a PreparedStatement object for the given SQL. QueryRunner methods always call this method to prepare statements for them. Subclasses can override this method to provide special PreparedStatement configuration if needed. This implementation simply calls conn.prepareStatement(sql). 104 | * 105 | * @param conn 106 | * The Connection used to create the PreparedStatement 107 | * @param sql 108 | * The SQL statement to prepare. 109 | * @return An initialized PreparedStatement. 110 | * @throws java.sql.SQLException 111 | * if a database access error occurs 112 | */ 113 | protected PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException { 114 | 115 | return conn.prepareStatement(sql); 116 | } 117 | 118 | /** 119 | * Factory method that creates and initializes a Connection object. QueryRunner methods always call this method to retrieve connections from its DataSource. Subclasses can override this method to provide special Connection configuration if needed. This implementation simply calls ds.getConnection(). 120 | * 121 | * @return An initialized Connection. 122 | * @throws java.sql.SQLException 123 | * if a database access error occurs 124 | * @since DbUtils 1.1 125 | */ 126 | protected Connection prepareConnection() throws SQLException { 127 | if (this.getDataSource() == null) { 128 | throw new SQLException("QueryRunner requires a DataSource to be " + "invoked in this way, or a Connection should be passed in"); 129 | } 130 | return this.getDataSource().getConnection(); 131 | } 132 | 133 | /** 134 | * Fill the PreparedStatement replacement parameters with the given objects. 135 | * 136 | * @param stmt 137 | * PreparedStatement to fill 138 | * @param params 139 | * Query replacement parameters; null is a valid value to pass in. 140 | * @throws java.sql.SQLException 141 | * if a database access error occurs 142 | */ 143 | public void fillStatement(PreparedStatement stmt, Object... params) throws SQLException { 144 | 145 | // check the parameter count, if we can 146 | ParameterMetaData pmd = null; 147 | if (!pmdKnownBroken) { 148 | pmd = stmt.getParameterMetaData(); 149 | int stmtCount = pmd.getParameterCount(); 150 | int paramsCount = params == null ? 0 : params.length; 151 | 152 | if (stmtCount != paramsCount) { 153 | throw new SQLException("Wrong number of parameters: expected " + stmtCount + ", was given " + paramsCount); 154 | } 155 | } 156 | 157 | // nothing to do here 158 | if (params == null) { 159 | return; 160 | } 161 | 162 | for (int i = 0; i < params.length; i++) { 163 | if (params[i] != null) { 164 | stmt.setObject(i + 1, params[i]); 165 | } else { 166 | // VARCHAR works with many drivers regardless 167 | // of the actual column type. Oddly, NULL and 168 | // OTHER don't work with Oracle's drivers. 169 | int sqlType = Types.VARCHAR; 170 | if (!pmdKnownBroken) { 171 | try { 172 | /* 173 | * It's not possible for pmdKnownBroken to change from true to false, (once true, always true) so pmd cannot be null here. 174 | */ 175 | sqlType = pmd.getParameterType(i + 1); 176 | } 177 | catch (SQLException e) { 178 | pmdKnownBroken = true; 179 | } 180 | } 181 | stmt.setNull(i + 1, sqlType); 182 | } 183 | } 184 | } 185 | 186 | /** 187 | * Fill the PreparedStatement replacement parameters with the given object's bean property values. 188 | * 189 | * @param stmt 190 | * PreparedStatement to fill 191 | * @param bean 192 | * a JavaBean object 193 | * @param properties 194 | * an ordered array of properties; this gives the order to insert values in the statement 195 | * @throws java.sql.SQLException 196 | * if a database access error occurs 197 | */ 198 | public void fillStatementWithBean(PreparedStatement stmt, Object bean, PropertyDescriptor[] properties) throws SQLException { 199 | Object[] params = new Object[properties.length]; 200 | for (int i = 0; i < properties.length; i++) { 201 | PropertyDescriptor property = properties[i]; 202 | Object value = null; 203 | Method method = property.getReadMethod(); 204 | if (method == null) { 205 | throw new RuntimeException("No read method for bean property " + bean.getClass() + " " + property.getName()); 206 | } 207 | try { 208 | value = method.invoke(bean, new Object[0]); 209 | } 210 | catch (InvocationTargetException e) { 211 | throw new RuntimeException("Couldn't invoke method: " + method, e); 212 | } 213 | catch (IllegalArgumentException e) { 214 | throw new RuntimeException("Couldn't invoke method with 0 arguments: " + method, e); 215 | } 216 | catch (IllegalAccessException e) { 217 | throw new RuntimeException("Couldn't invoke method: " + method, e); 218 | } 219 | params[i] = value; 220 | } 221 | fillStatement(stmt, params); 222 | } 223 | 224 | /** 225 | * Fill the PreparedStatement replacement parameters with the given object's bean property values. 226 | * 227 | * @param stmt 228 | * PreparedStatement to fill 229 | * @param bean 230 | * A JavaBean object 231 | * @param propertyNames 232 | * An ordered array of property names (these should match the getters/setters); this gives the order to insert values in the statement 233 | * @throws java.sql.SQLException 234 | * If a database access error occurs 235 | */ 236 | public void fillStatementWithBean(PreparedStatement stmt, Object bean, String... propertyNames) throws SQLException { 237 | PropertyDescriptor[] descriptors; 238 | try { 239 | descriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 240 | } 241 | catch (IntrospectionException e) { 242 | throw new RuntimeException("Couldn't introspect bean " + bean.getClass().toString(), e); 243 | } 244 | PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length]; 245 | for (int i = 0; i < propertyNames.length; i++) { 246 | String propertyName = propertyNames[i]; 247 | if (propertyName == null) { 248 | throw new NullPointerException("propertyName can't be null: " + i); 249 | } 250 | boolean found = false; 251 | for (int j = 0; j < descriptors.length; j++) { 252 | PropertyDescriptor descriptor = descriptors[j]; 253 | if (propertyName.equals(descriptor.getName())) { 254 | sorted[i] = descriptor; 255 | found = true; 256 | break; 257 | } 258 | } 259 | if (!found) { 260 | throw new RuntimeException("Couldn't find bean property: " + bean.getClass() + " " + propertyName); 261 | } 262 | } 263 | fillStatementWithBean(stmt, bean, sorted); 264 | } 265 | 266 | /** 267 | * Throws a new exception with a more informative error message. 268 | * 269 | * @param cause 270 | * The original exception that will be chained to the new exception when it's rethrown. 271 | * @param sql 272 | * The query that was executing when the exception happened. 273 | * @param params 274 | * The query replacement parameters; null is a valid value to pass in. 275 | * @throws java.sql.SQLException 276 | * if a database access error occurs 277 | */ 278 | protected void rethrow(SQLException cause, String sql, Object... params) throws SQLException { 279 | 280 | String causeMessage = cause.getMessage(); 281 | if (causeMessage == null) { 282 | causeMessage = ""; 283 | } 284 | StringBuffer msg = new StringBuffer(causeMessage); 285 | 286 | msg.append(" Query: "); 287 | msg.append(sql); 288 | msg.append(" Parameters: "); 289 | 290 | if (params == null) { 291 | msg.append("[]"); 292 | } else { 293 | msg.append(Arrays.deepToString(params)); 294 | } 295 | 296 | SQLException e = new SQLException(msg.toString(), cause.getSQLState(), cause.getErrorCode()); 297 | e.setNextException(cause); 298 | 299 | throw e; 300 | } 301 | 302 | /** 303 | * Wrap the ResultSet in a decorator before processing it. This implementation returns the ResultSet it is given without any decoration. 304 | *

    305 | * Often, the implementation of this method can be done in an anonymous inner class like this: 306 | *

    307 | * 308 | *
    309 | 	 * 
    310 | 	 * QueryRunner run = new QueryRunner() {
    311 | 	 * 
    312 | 	 * 	protected ResultSet wrap(ResultSet rs) {
    313 | 	 * 		return StringTrimmedResultSet.wrap(rs);
    314 | 	 * 	}
    315 | 	 * };
    316 | 	 * 
    317 | * 318 | * @param rs 319 | * The ResultSet to decorate; never null. 320 | * @return The ResultSet wrapped in some decorator. 321 | */ 322 | protected ResultSet wrap(ResultSet rs) { 323 | return rs; 324 | } 325 | 326 | /** 327 | * Close a Connection. This implementation avoids closing if null and does not suppress any exceptions. Subclasses can override to provide special handling like logging. 328 | * 329 | * @param conn 330 | * Connection to close 331 | * @throws java.sql.SQLException 332 | * if a database access error occurs 333 | * @since DbUtils 1.1 334 | */ 335 | protected void close(Connection conn) throws SQLException { 336 | DbUtils.close(conn); 337 | } 338 | 339 | /** 340 | * Close a Statement. This implementation avoids closing if null and does not suppress any exceptions. Subclasses can override to provide special handling like logging. 341 | * 342 | * @param stmt 343 | * Statement to close 344 | * @throws java.sql.SQLException 345 | * if a database access error occurs 346 | * @since DbUtils 1.1 347 | */ 348 | protected void close(Statement stmt) throws SQLException { 349 | DbUtils.close(stmt); 350 | } 351 | 352 | /** 353 | * Close a ResultSet. This implementation avoids closing if null and does not suppress any exceptions. Subclasses can override to provide special handling like logging. 354 | * 355 | * @param rs 356 | * ResultSet to close 357 | * @throws java.sql.SQLException 358 | * if a database access error occurs 359 | * @since DbUtils 1.1 360 | */ 361 | protected void close(ResultSet rs) throws SQLException { 362 | DbUtils.close(rs); 363 | } 364 | 365 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/BeanProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils; 5 | 6 | import java.beans.BeanInfo; 7 | import java.beans.IntrospectionException; 8 | import java.beans.Introspector; 9 | import java.beans.PropertyDescriptor; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.sql.ResultSet; 13 | import java.sql.ResultSetMetaData; 14 | import java.sql.SQLException; 15 | import java.sql.SQLXML; 16 | import java.sql.Timestamp; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | /** 24 | *

    25 | * BeanProcessor matches column names to bean property names and converts ResultSet columns into objects for those bean properties. Subclasses should override the methods in the processing chain to customize behavior. 26 | *

    27 | *

    28 | * This class is thread-safe. 29 | *

    30 | * 31 | * @see BasicRowProcessor 32 | * @since DbUtils 1.1 33 | */ 34 | public class BeanProcessor { 35 | 36 | /** 37 | * Special array value used by mapColumnsToProperties that indicates there is no bean property that matches a column from a ResultSet. 38 | */ 39 | protected static final int PROPERTY_NOT_FOUND = -1; 40 | 41 | /** 42 | * Set a bean's primitive properties to these defaults when SQL NULL is returned. These are the same as the defaults that ResultSet get* methods return in the event of a NULL column. 43 | */ 44 | private static final Map, Object> primitiveDefaults = new HashMap, Object>(); 45 | 46 | /** 47 | * ResultSet column to bean property name overrides. 48 | */ 49 | private final Map columnToPropertyOverrides; 50 | 51 | static { 52 | primitiveDefaults.put(Integer.TYPE, Integer.valueOf(0)); 53 | primitiveDefaults.put(Short.TYPE, Short.valueOf((short) 0)); 54 | primitiveDefaults.put(Byte.TYPE, Byte.valueOf((byte) 0)); 55 | primitiveDefaults.put(Float.TYPE, Float.valueOf(0f)); 56 | primitiveDefaults.put(Double.TYPE, Double.valueOf(0d)); 57 | primitiveDefaults.put(Long.TYPE, Long.valueOf(0L)); 58 | primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE); 59 | primitiveDefaults.put(Character.TYPE, Character.valueOf((char) 0)); 60 | } 61 | 62 | /** 63 | * Constructor for BeanProcessor. 64 | */ 65 | public BeanProcessor() { 66 | this(new HashMap()); 67 | } 68 | 69 | /** 70 | * Constructor for BeanProcessor configured with column to property name overrides. 71 | * 72 | * @param columnToPropertyOverrides 73 | * ResultSet column to bean property name overrides 74 | * @since 1.5 75 | */ 76 | public BeanProcessor(Map columnToPropertyOverrides) { 77 | super(); 78 | if (columnToPropertyOverrides == null) { 79 | throw new IllegalArgumentException("columnToPropertyOverrides map cannot be null"); 80 | } 81 | this.columnToPropertyOverrides = columnToPropertyOverrides; 82 | } 83 | 84 | /** 85 | * Convert a ResultSet row into a JavaBean. This implementation uses reflection and BeanInfo classes to match column names to bean property names. Properties are matched to columns based on several factors:
    86 | *
      87 | *
    1. The class has a writable property with the same name as a column. The name comparison is case insensitive.
    2. 88 | *
    3. The column type can be converted to the property's set method parameter type with a ResultSet.get* method. If the conversion fails (ie. the property was an int and the column was a Timestamp) an SQLException is thrown.
    4. 89 | *
    90 | *

    91 | * Primitive bean properties are set to their defaults when SQL NULL is returned from the ResultSet. Numeric fields are set to 0 and booleans are set to false. Object bean properties are set to null when SQL NULL is returned. This is the same behavior as the ResultSet get* methods. 92 | *

    93 | * 94 | * @param 95 | * The type of bean to create 96 | * @param rs 97 | * ResultSet that supplies the bean data 98 | * @param type 99 | * Class from which to create the bean instance 100 | * @throws java.sql.SQLException 101 | * if a database access error occurs 102 | * @return the newly created bean 103 | */ 104 | public T toBean(ResultSet rs, Class type) throws SQLException { 105 | 106 | PropertyDescriptor[] props = this.propertyDescriptors(type); 107 | 108 | ResultSetMetaData rsmd = rs.getMetaData(); 109 | int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); 110 | 111 | return this.createBean(rs, type, props, columnToProperty); 112 | } 113 | 114 | /** 115 | * Convert a ResultSet into a List of JavaBeans. This implementation uses reflection and BeanInfo classes to match column names to bean property names. Properties are matched to columns based on several factors:
    116 | *
      117 | *
    1. The class has a writable property with the same name as a column. The name comparison is case insensitive.
    2. 118 | *
    3. The column type can be converted to the property's set method parameter type with a ResultSet.get* method. If the conversion fails (ie. the property was an int and the column was a Timestamp) an SQLException is thrown.
    4. 119 | *
    120 | *

    121 | * Primitive bean properties are set to their defaults when SQL NULL is returned from the ResultSet. Numeric fields are set to 0 and booleans are set to false. Object bean properties are set to null when SQL NULL is returned. This is the same behavior as the ResultSet get* methods. 122 | *

    123 | * 124 | * @param 125 | * The type of bean to create 126 | * @param rs 127 | * ResultSet that supplies the bean data 128 | * @param type 129 | * Class from which to create the bean instance 130 | * @throws java.sql.SQLException 131 | * if a database access error occurs 132 | * @return the newly created List of beans 133 | */ 134 | public List toBeanList(ResultSet rs, Class type) throws SQLException { 135 | List results = new ArrayList(); 136 | 137 | if (!rs.next()) { 138 | return results; 139 | } 140 | 141 | PropertyDescriptor[] props = this.propertyDescriptors(type); 142 | ResultSetMetaData rsmd = rs.getMetaData(); 143 | int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); 144 | 145 | do { 146 | results.add(this.createBean(rs, type, props, columnToProperty)); 147 | } 148 | while (rs.next()); 149 | 150 | return results; 151 | } 152 | 153 | /** 154 | * Creates a new object and initializes its fields from the ResultSet. 155 | * 156 | * @param 157 | * The type of bean to create 158 | * @param rs 159 | * The result set. 160 | * @param type 161 | * The bean type (the return type of the object). 162 | * @param props 163 | * The property descriptors. 164 | * @param columnToProperty 165 | * The column indices in the result set. 166 | * @return An initialized object. 167 | * @throws java.sql.SQLException 168 | * if a database error occurs. 169 | */ 170 | private T createBean(ResultSet rs, Class type, PropertyDescriptor[] props, int[] columnToProperty) throws SQLException { 171 | 172 | T bean = this.newInstance(type); 173 | 174 | for (int i = 1; i < columnToProperty.length; i++) { 175 | 176 | if (columnToProperty[i] == PROPERTY_NOT_FOUND) { 177 | continue; 178 | } 179 | 180 | PropertyDescriptor prop = props[columnToProperty[i]]; 181 | Class propType = prop.getPropertyType(); 182 | 183 | Object value = this.processColumn(rs, i, propType); 184 | 185 | if (propType != null && value == null && propType.isPrimitive()) { 186 | value = primitiveDefaults.get(propType); 187 | } 188 | 189 | this.callSetter(bean, prop, value); 190 | } 191 | 192 | return bean; 193 | } 194 | 195 | /** 196 | * Calls the setter method on the target object for the given property. If no setter method exists for the property, this method does nothing. 197 | * 198 | * @param target 199 | * The object to set the property on. 200 | * @param prop 201 | * The property to set. 202 | * @param value 203 | * The value to pass into the setter. 204 | * @throws java.sql.SQLException 205 | * if an error occurs setting the property. 206 | */ 207 | private void callSetter(Object target, PropertyDescriptor prop, Object value) throws SQLException { 208 | 209 | Method setter = prop.getWriteMethod(); 210 | 211 | if (setter == null) { 212 | return; 213 | } 214 | 215 | Class[] params = setter.getParameterTypes(); 216 | try { 217 | // convert types for some popular ones 218 | if (value instanceof java.util.Date) { 219 | final String targetType = params[0].getName(); 220 | if ("java.sql.Date".equals(targetType)) { 221 | value = new java.sql.Date(((java.util.Date) value).getTime()); 222 | } else if ("java.sql.Time".equals(targetType)) { 223 | value = new java.sql.Time(((java.util.Date) value).getTime()); 224 | } else if ("java.sql.Timestamp".equals(targetType)) { 225 | value = new Timestamp(((java.util.Date) value).getTime()); 226 | } 227 | } 228 | 229 | // Don't call setter if the value object isn't the right type 230 | if (this.isCompatibleType(value, params[0])) { 231 | setter.invoke(target, new Object[] { value }); 232 | } else { 233 | throw new SQLException("Cannot set " + prop.getName() + ": incompatible types, cannot convert " + value.getClass().getName() + " to " + params[0].getName()); 234 | // value cannot be null here because isCompatibleType allows null 235 | } 236 | 237 | } 238 | catch (IllegalArgumentException e) { 239 | throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); 240 | 241 | } 242 | catch (IllegalAccessException e) { 243 | throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); 244 | 245 | } 246 | catch (InvocationTargetException e) { 247 | throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); 248 | } 249 | } 250 | 251 | /** 252 | * ResultSet.getObject() returns an Integer object for an INT column. The setter method for the property might take an Integer or a primitive int. This method returns true if the value can be successfully passed into the setter method. Remember, Method.invoke() handles the unwrapping of Integer into an int. 253 | * 254 | * @param value 255 | * The value to be passed into the setter method. 256 | * @param type 257 | * The setter's parameter type (non-null) 258 | * @return boolean True if the value is compatible (null => true) 259 | */ 260 | private boolean isCompatibleType(Object value, Class type) { 261 | // Do object check first, then primitives 262 | if (value == null || type.isInstance(value)) { 263 | return true; 264 | 265 | } else if (type.equals(Integer.TYPE) && Integer.class.isInstance(value)) { 266 | return true; 267 | 268 | } else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) { 269 | return true; 270 | 271 | } else if (type.equals(Double.TYPE) && Double.class.isInstance(value)) { 272 | return true; 273 | 274 | } else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) { 275 | return true; 276 | 277 | } else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) { 278 | return true; 279 | 280 | } else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) { 281 | return true; 282 | 283 | } else if (type.equals(Character.TYPE) && Character.class.isInstance(value)) { 284 | return true; 285 | 286 | } else if (type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) { 287 | return true; 288 | 289 | } 290 | return false; 291 | 292 | } 293 | 294 | /** 295 | * Factory method that returns a new instance of the given Class. This is called at the start of the bean creation process and may be overridden to provide custom behavior like returning a cached bean instance. 296 | * 297 | * @param 298 | * The type of object to create 299 | * @param c 300 | * The Class to create an object from. 301 | * @return A newly created object of the Class. 302 | * @throws java.sql.SQLException 303 | * if creation failed. 304 | */ 305 | protected T newInstance(Class c) throws SQLException { 306 | try { 307 | return c.newInstance(); 308 | 309 | } 310 | catch (InstantiationException e) { 311 | throw new SQLException("Cannot create " + c.getName() + ": " + e.getMessage()); 312 | 313 | } 314 | catch (IllegalAccessException e) { 315 | throw new SQLException("Cannot create " + c.getName() + ": " + e.getMessage()); 316 | } 317 | } 318 | 319 | /** 320 | * Returns a PropertyDescriptor[] for the given Class. 321 | * 322 | * @param c 323 | * The Class to retrieve PropertyDescriptors for. 324 | * @return A PropertyDescriptor[] describing the Class. 325 | * @throws java.sql.SQLException 326 | * if introspection failed. 327 | */ 328 | private PropertyDescriptor[] propertyDescriptors(Class c) throws SQLException { 329 | // Introspector caches BeanInfo classes for better performance 330 | BeanInfo beanInfo = null; 331 | try { 332 | beanInfo = Introspector.getBeanInfo(c); 333 | 334 | } 335 | catch (IntrospectionException e) { 336 | throw new SQLException("Bean introspection failed: " + e.getMessage()); 337 | } 338 | 339 | return beanInfo.getPropertyDescriptors(); 340 | } 341 | 342 | /** 343 | * The positions in the returned array represent column numbers. The values stored at each position represent the index in the PropertyDescriptor[] for the bean property that matches the column name. If no bean property was found for a column, the position is set to PROPERTY_NOT_FOUND. 344 | * 345 | * @param rsmd 346 | * The ResultSetMetaData containing column information. 347 | * @param props 348 | * The bean property descriptors. 349 | * @throws java.sql.SQLException 350 | * if a database access error occurs 351 | * @return An int[] with column index to property index mappings. The 0th element is meaningless because JDBC column indexing starts at 1. 352 | */ 353 | protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, PropertyDescriptor[] props) throws SQLException { 354 | 355 | int cols = rsmd.getColumnCount(); 356 | int[] columnToProperty = new int[cols + 1]; 357 | Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND); 358 | 359 | for (int col = 1; col <= cols; col++) { 360 | String columnName = rsmd.getColumnLabel(col); 361 | if (null == columnName || 0 == columnName.length()) { 362 | columnName = rsmd.getColumnName(col); 363 | } 364 | String propertyName = columnToPropertyOverrides.get(columnName); 365 | if (propertyName == null) { 366 | propertyName = columnName; 367 | } 368 | for (int i = 0; i < props.length; i++) { 369 | 370 | if (propertyName.equalsIgnoreCase(props[i].getName())) { 371 | columnToProperty[col] = i; 372 | break; 373 | } 374 | } 375 | } 376 | 377 | return columnToProperty; 378 | } 379 | 380 | /** 381 | * Convert a ResultSet column into an object. Simple implementations could just call rs.getObject(index) while more complex implementations could perform type manipulation to match the column's type to the bean property type. 382 | *

    383 | * This implementation calls the appropriate ResultSet getter method for the given property type to perform the type conversion. If the property type doesn't match one of the supported ResultSet types, getObject is called. 384 | *

    385 | * 386 | * @param rs 387 | * The ResultSet currently being processed. It is positioned on a valid row before being passed into this method. 388 | * @param index 389 | * The current column index being processed. 390 | * @param propType 391 | * The bean property type that this column needs to be converted into. 392 | * @throws java.sql.SQLException 393 | * if a database access error occurs 394 | * @return The object from the ResultSet at the given column index after optional type processing or null if the column value was SQL NULL. 395 | */ 396 | protected Object processColumn(ResultSet rs, int index, Class propType) throws SQLException { 397 | 398 | if (!propType.isPrimitive() && rs.getObject(index) == null) { 399 | return null; 400 | } 401 | 402 | if (propType.equals(String.class)) { 403 | return rs.getString(index); 404 | 405 | } else if (propType.equals(Integer.TYPE) || propType.equals(Integer.class)) { 406 | return Integer.valueOf(rs.getInt(index)); 407 | 408 | } else if (propType.equals(Boolean.TYPE) || propType.equals(Boolean.class)) { 409 | return Boolean.valueOf(rs.getBoolean(index)); 410 | 411 | } else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) { 412 | return Long.valueOf(rs.getLong(index)); 413 | 414 | } else if (propType.equals(Double.TYPE) || propType.equals(Double.class)) { 415 | return Double.valueOf(rs.getDouble(index)); 416 | 417 | } else if (propType.equals(Float.TYPE) || propType.equals(Float.class)) { 418 | return Float.valueOf(rs.getFloat(index)); 419 | 420 | } else if (propType.equals(Short.TYPE) || propType.equals(Short.class)) { 421 | return Short.valueOf(rs.getShort(index)); 422 | 423 | } else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) { 424 | return Byte.valueOf(rs.getByte(index)); 425 | 426 | } else if (propType.equals(Timestamp.class)) { 427 | return rs.getTimestamp(index); 428 | 429 | } else if (propType.equals(SQLXML.class)) { 430 | return rs.getSQLXML(index); 431 | 432 | } else { 433 | return rs.getObject(index); 434 | } 435 | 436 | } 437 | 438 | } -------------------------------------------------------------------------------- /DbHelper/src/main/java/com/opensource/dbhelp/dbutils/wrappers/SqlNullCheckedResultSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 3 | */ 4 | package com.opensource.dbhelp.dbutils.wrappers; 5 | 6 | import java.io.InputStream; 7 | import java.io.Reader; 8 | import java.lang.reflect.InvocationHandler; 9 | import java.lang.reflect.Method; 10 | import java.math.BigDecimal; 11 | import java.net.URL; 12 | import java.sql.Blob; 13 | import java.sql.Clob; 14 | import java.sql.Date; 15 | import java.sql.Ref; 16 | import java.sql.ResultSet; 17 | import java.sql.Time; 18 | import java.sql.Timestamp; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import com.opensource.dbhelp.dbutils.ProxyFactory; 23 | 24 | /** 25 | * Decorates a ResultSet with checks for a SQL NULL value on each getXXX method. If a column value obtained by a getXXX method is not SQL NULL, the column value is returned. If the column value is SQL null, an alternate value is returned. The alternate value defaults to the Java null value, which can be overridden for instances of the class. 26 | *

    27 | * Usage example:

    28 | * 29 | *
     30 |  * Connection conn = // somehow get a connection
     31 |  * Statement stmt = conn.createStatement();
     32 |  * ResultSet rs = stmt.executeQuery("SELECT col1, col2 FROM table1");
     33 |  * 
     34 |  * // Wrap the result set for SQL NULL checking
     35 |  * SqlNullCheckedResultSet wrapper = new SqlNullCheckedResultSet(rs);
     36 |  * wrapper.setNullString("---N/A---"); // Set null string
     37 |  * wrapper.setNullInt(-999); // Set null integer
     38 |  * rs = ProxyFactory.instance().createResultSet(wrapper);
     39 |  * 
     40 |  * while (rs.next()) {
     41 |  *     // If col1 is SQL NULL, value returned will be "---N/A---"
     42 |  *     String col1 = rs.getString("col1");
     43 |  *     // If col2 is SQL NULL, value returned will be -999
     44 |  *     int col2 = rs.getInt("col2");
     45 |  * }
     46 |  * rs.close();
     47 |  * 
    48 | * 49 | *
    50 | *

    51 | *

    52 | * Unlike some other classes in DbUtils, this class is NOT thread-safe. 53 | *

    54 | */ 55 | public class SqlNullCheckedResultSet implements InvocationHandler { 56 | 57 | /** 58 | * Maps normal method names (ie. "getBigDecimal") to the corresponding null Method object (ie. getNullBigDecimal). 59 | */ 60 | private static final Map nullMethods = new HashMap(); 61 | 62 | /** 63 | * The {@code getNull} string prefix. 64 | * 65 | * @since 1.4 66 | */ 67 | private static final String GET_NULL_PREFIX = "getNull"; 68 | 69 | static { 70 | Method[] methods = SqlNullCheckedResultSet.class.getMethods(); 71 | for (int i = 0; i < methods.length; i++) { 72 | String methodName = methods[i].getName(); 73 | 74 | if (methodName.startsWith(GET_NULL_PREFIX)) { 75 | String normalName = "get" + methodName.substring(GET_NULL_PREFIX.length()); 76 | nullMethods.put(normalName, methods[i]); 77 | } 78 | } 79 | } 80 | 81 | /** 82 | * The factory to create proxies with. 83 | */ 84 | private static final ProxyFactory factory = ProxyFactory.instance(); 85 | 86 | /** 87 | * Wraps the ResultSet in an instance of this class. This is equivalent to: 88 | * 89 | *
     90 | 	 * ProxyFactory.instance().createResultSet(new SqlNullCheckedResultSet(rs));
     91 | 	 * 
    92 | * 93 | * @param rs 94 | * The ResultSet to wrap. 95 | * @return wrapped ResultSet 96 | */ 97 | public static ResultSet wrap(ResultSet rs) { 98 | return factory.createResultSet(new SqlNullCheckedResultSet(rs)); 99 | } 100 | 101 | private InputStream nullAsciiStream = null; 102 | 103 | private BigDecimal nullBigDecimal = null; 104 | 105 | private InputStream nullBinaryStream = null; 106 | 107 | private Blob nullBlob = null; 108 | 109 | private boolean nullBoolean = false; 110 | 111 | private byte nullByte = 0; 112 | 113 | private byte[] nullBytes = null; 114 | 115 | private Reader nullCharacterStream = null; 116 | 117 | private Clob nullClob = null; 118 | 119 | private Date nullDate = null; 120 | 121 | private double nullDouble = 0.0; 122 | 123 | private float nullFloat = 0.0f; 124 | 125 | private int nullInt = 0; 126 | 127 | private long nullLong = 0; 128 | 129 | private Object nullObject = null; 130 | 131 | private Ref nullRef = null; 132 | 133 | private short nullShort = 0; 134 | 135 | private String nullString = null; 136 | 137 | private Time nullTime = null; 138 | 139 | private Timestamp nullTimestamp = null; 140 | 141 | private URL nullURL = null; 142 | 143 | /** 144 | * The wrapped result. 145 | */ 146 | private final ResultSet rs; 147 | 148 | /** 149 | * Constructs a new instance of SqlNullCheckedResultSet to wrap the specified ResultSet. 150 | * 151 | * @param rs 152 | * ResultSet to wrap 153 | */ 154 | public SqlNullCheckedResultSet(ResultSet rs) { 155 | super(); 156 | this.rs = rs; 157 | } 158 | 159 | /** 160 | * Returns the value when a SQL null is encountered as the result of invoking a getAsciiStream method. 161 | * 162 | * @return the value 163 | */ 164 | public InputStream getNullAsciiStream() { 165 | return this.nullAsciiStream; 166 | } 167 | 168 | /** 169 | * Returns the value when a SQL null is encountered as the result of invoking a getBigDecimal method. 170 | * 171 | * @return the value 172 | */ 173 | public BigDecimal getNullBigDecimal() { 174 | return this.nullBigDecimal; 175 | } 176 | 177 | /** 178 | * Returns the value when a SQL null is encountered as the result of invoking a getBinaryStream method. 179 | * 180 | * @return the value 181 | */ 182 | public InputStream getNullBinaryStream() { 183 | return this.nullBinaryStream; 184 | } 185 | 186 | /** 187 | * Returns the value when a SQL null is encountered as the result of invoking a getBlob method. 188 | * 189 | * @return the value 190 | */ 191 | public Blob getNullBlob() { 192 | return this.nullBlob; 193 | } 194 | 195 | /** 196 | * Returns the value when a SQL null is encountered as the result of invoking a getBoolean method. 197 | * 198 | * @return the value 199 | */ 200 | public boolean getNullBoolean() { 201 | return this.nullBoolean; 202 | } 203 | 204 | /** 205 | * Returns the value when a SQL null is encountered as the result of invoking a getByte method. 206 | * 207 | * @return the value 208 | */ 209 | public byte getNullByte() { 210 | return this.nullByte; 211 | } 212 | 213 | /** 214 | * Returns the value when a SQL null is encountered as the result of invoking a getBytes method. 215 | * 216 | * @return the value 217 | */ 218 | public byte[] getNullBytes() { 219 | if (this.nullBytes == null) { 220 | return null; 221 | } 222 | byte[] copy = new byte[this.nullBytes.length]; 223 | System.arraycopy(this.nullBytes, 0, copy, 0, this.nullBytes.length); 224 | return copy; 225 | } 226 | 227 | /** 228 | * Returns the value when a SQL null is encountered as the result of invoking a getCharacterStream method. 229 | * 230 | * @return the value 231 | */ 232 | public Reader getNullCharacterStream() { 233 | return this.nullCharacterStream; 234 | } 235 | 236 | /** 237 | * Returns the value when a SQL null is encountered as the result of invoking a getClob method. 238 | * 239 | * @return the value 240 | */ 241 | public Clob getNullClob() { 242 | return this.nullClob; 243 | } 244 | 245 | /** 246 | * Returns the value when a SQL null is encountered as the result of invoking a getDate method. 247 | * 248 | * @return the value 249 | */ 250 | public Date getNullDate() { 251 | return this.nullDate; 252 | } 253 | 254 | /** 255 | * Returns the value when a SQL null is encountered as the result of invoking a getDouble method. 256 | * 257 | * @return the value 258 | */ 259 | public double getNullDouble() { 260 | return this.nullDouble; 261 | } 262 | 263 | /** 264 | * Returns the value when a SQL null is encountered as the result of invoking a getFloat method. 265 | * 266 | * @return the value 267 | */ 268 | public float getNullFloat() { 269 | return this.nullFloat; 270 | } 271 | 272 | /** 273 | * Returns the value when a SQL null is encountered as the result of invoking a getInt method. 274 | * 275 | * @return the value 276 | */ 277 | public int getNullInt() { 278 | return this.nullInt; 279 | } 280 | 281 | /** 282 | * Returns the value when a SQL null is encountered as the result of invoking a getLong method. 283 | * 284 | * @return the value 285 | */ 286 | public long getNullLong() { 287 | return this.nullLong; 288 | } 289 | 290 | /** 291 | * Returns the value when a SQL null is encountered as the result of invoking a getObject method. 292 | * 293 | * @return the value 294 | */ 295 | public Object getNullObject() { 296 | return this.nullObject; 297 | } 298 | 299 | /** 300 | * Returns the value when a SQL null is encountered as the result of invoking a getRef method. 301 | * 302 | * @return the value 303 | */ 304 | public Ref getNullRef() { 305 | return this.nullRef; 306 | } 307 | 308 | /** 309 | * Returns the value when a SQL null is encountered as the result of invoking a getShort method. 310 | * 311 | * @return the value 312 | */ 313 | public short getNullShort() { 314 | return this.nullShort; 315 | } 316 | 317 | /** 318 | * Returns the value when a SQL null is encountered as the result of invoking a getString method. 319 | * 320 | * @return the value 321 | */ 322 | public String getNullString() { 323 | return this.nullString; 324 | } 325 | 326 | /** 327 | * Returns the value when a SQL null is encountered as the result of invoking a getTime method. 328 | * 329 | * @return the value 330 | */ 331 | public Time getNullTime() { 332 | return this.nullTime; 333 | } 334 | 335 | /** 336 | * Returns the value when a SQL null is encountered as the result of invoking a getTimestamp method. 337 | * 338 | * @return the value 339 | */ 340 | public Timestamp getNullTimestamp() { 341 | return this.nullTimestamp; 342 | } 343 | 344 | /** 345 | * Returns the value when a SQL null is encountered as the result of invoking a getURL method. 346 | * 347 | * @return the value 348 | */ 349 | public URL getNullURL() { 350 | return this.nullURL; 351 | } 352 | 353 | /** 354 | * Intercepts calls to get* methods and calls the appropriate getNull* method if the ResultSet returned null. 355 | * 356 | * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[]) 357 | * @param proxy 358 | * Not used; all method calls go to the internal result set 359 | * @param method 360 | * The method to invoke on the result set 361 | * @param args 362 | * The arguments to pass to the result set 363 | * @return null checked result 364 | * @throws Throwable 365 | * error 366 | */ 367 | @Override 368 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 369 | 370 | Object result = method.invoke(this.rs, args); 371 | 372 | Method nullMethod = nullMethods.get(method.getName()); 373 | 374 | // Check nullMethod != null first so that we don't call wasNull() 375 | // before a true getter method was invoked on the ResultSet. 376 | return (nullMethod != null && this.rs.wasNull()) ? nullMethod.invoke(this, (Object[]) null) : result; 377 | } 378 | 379 | /** 380 | * Sets the value to return when a SQL null is encountered as the result of invoking a getAsciiStream method. 381 | * 382 | * @param nullAsciiStream 383 | * the value 384 | */ 385 | public void setNullAsciiStream(InputStream nullAsciiStream) { 386 | this.nullAsciiStream = nullAsciiStream; 387 | } 388 | 389 | /** 390 | * Sets the value to return when a SQL null is encountered as the result of invoking a getBigDecimal method. 391 | * 392 | * @param nullBigDecimal 393 | * the value 394 | */ 395 | public void setNullBigDecimal(BigDecimal nullBigDecimal) { 396 | this.nullBigDecimal = nullBigDecimal; 397 | } 398 | 399 | /** 400 | * Sets the value to return when a SQL null is encountered as the result of invoking a getBinaryStream method. 401 | * 402 | * @param nullBinaryStream 403 | * the value 404 | */ 405 | public void setNullBinaryStream(InputStream nullBinaryStream) { 406 | this.nullBinaryStream = nullBinaryStream; 407 | } 408 | 409 | /** 410 | * Sets the value to return when a SQL null is encountered as the result of invoking a getBlob method. 411 | * 412 | * @param nullBlob 413 | * the value 414 | */ 415 | public void setNullBlob(Blob nullBlob) { 416 | this.nullBlob = nullBlob; 417 | } 418 | 419 | /** 420 | * Sets the value to return when a SQL null is encountered as the result of invoking a getBoolean method. 421 | * 422 | * @param nullBoolean 423 | * the value 424 | */ 425 | public void setNullBoolean(boolean nullBoolean) { 426 | this.nullBoolean = nullBoolean; 427 | } 428 | 429 | /** 430 | * Sets the value to return when a SQL null is encountered as the result of invoking a getByte method. 431 | * 432 | * @param nullByte 433 | * the value 434 | */ 435 | public void setNullByte(byte nullByte) { 436 | this.nullByte = nullByte; 437 | } 438 | 439 | /** 440 | * Sets the value to return when a SQL null is encountered as the result of invoking a getBytes method. 441 | * 442 | * @param nullBytes 443 | * the value 444 | */ 445 | public void setNullBytes(byte[] nullBytes) { 446 | byte[] copy = new byte[nullBytes.length]; 447 | System.arraycopy(nullBytes, 0, copy, 0, nullBytes.length); 448 | this.nullBytes = copy; 449 | } 450 | 451 | /** 452 | * Sets the value to return when a SQL null is encountered as the result of invoking a getCharacterStream method. 453 | * 454 | * @param nullCharacterStream 455 | * the value 456 | */ 457 | public void setNullCharacterStream(Reader nullCharacterStream) { 458 | this.nullCharacterStream = nullCharacterStream; 459 | } 460 | 461 | /** 462 | * Sets the value to return when a SQL null is encountered as the result of invoking a getClob method. 463 | * 464 | * @param nullClob 465 | * the value 466 | */ 467 | public void setNullClob(Clob nullClob) { 468 | this.nullClob = nullClob; 469 | } 470 | 471 | /** 472 | * Sets the value to return when a SQL null is encountered as the result of invoking a getDate method. 473 | * 474 | * @param nullDate 475 | * the value 476 | */ 477 | public void setNullDate(Date nullDate) { 478 | this.nullDate = nullDate; 479 | } 480 | 481 | /** 482 | * Sets the value to return when a SQL null is encountered as the result of invoking a getDouble method. 483 | * 484 | * @param nullDouble 485 | * the value 486 | */ 487 | public void setNullDouble(double nullDouble) { 488 | this.nullDouble = nullDouble; 489 | } 490 | 491 | /** 492 | * Sets the value to return when a SQL null is encountered as the result of invoking a getFloat method. 493 | * 494 | * @param nullFloat 495 | * the value 496 | */ 497 | public void setNullFloat(float nullFloat) { 498 | this.nullFloat = nullFloat; 499 | } 500 | 501 | /** 502 | * Sets the value to return when a SQL null is encountered as the result of invoking a getInt method. 503 | * 504 | * @param nullInt 505 | * the value 506 | */ 507 | public void setNullInt(int nullInt) { 508 | this.nullInt = nullInt; 509 | } 510 | 511 | /** 512 | * Sets the value to return when a SQL null is encountered as the result of invoking a getLong method. 513 | * 514 | * @param nullLong 515 | * the value 516 | */ 517 | public void setNullLong(long nullLong) { 518 | this.nullLong = nullLong; 519 | } 520 | 521 | /** 522 | * Sets the value to return when a SQL null is encountered as the result of invoking a getObject method. 523 | * 524 | * @param nullObject 525 | * the value 526 | */ 527 | public void setNullObject(Object nullObject) { 528 | this.nullObject = nullObject; 529 | } 530 | 531 | /** 532 | * Sets the value to return when a SQL null is encountered as the result of invoking a getRef method. 533 | * 534 | * @param nullRef 535 | * the value 536 | */ 537 | public void setNullRef(Ref nullRef) { 538 | this.nullRef = nullRef; 539 | } 540 | 541 | /** 542 | * Sets the value to return when a SQL null is encountered as the result of invoking a getShort method. 543 | * 544 | * @param nullShort 545 | * the value 546 | */ 547 | public void setNullShort(short nullShort) { 548 | this.nullShort = nullShort; 549 | } 550 | 551 | /** 552 | * Sets the value to return when a SQL null is encountered as the result of invoking a getString method. 553 | * 554 | * @param nullString 555 | * the value 556 | */ 557 | public void setNullString(String nullString) { 558 | this.nullString = nullString; 559 | } 560 | 561 | /** 562 | * Sets the value to return when a SQL null is encountered as the result of invoking a getTime method. 563 | * 564 | * @param nullTime 565 | * the value 566 | */ 567 | public void setNullTime(Time nullTime) { 568 | this.nullTime = nullTime; 569 | } 570 | 571 | /** 572 | * Sets the value to return when a SQL null is encountered as the result of invoking a getTimestamp method. 573 | * 574 | * @param nullTimestamp 575 | * the value 576 | */ 577 | public void setNullTimestamp(Timestamp nullTimestamp) { 578 | this.nullTimestamp = nullTimestamp; 579 | } 580 | 581 | /** 582 | * Sets the value to return when a SQL null is encountered as the result of invoking a getURL method. 583 | * 584 | * @param nullURL 585 | * the value 586 | */ 587 | public void setNullURL(URL nullURL) { 588 | this.nullURL = nullURL; 589 | } 590 | 591 | } --------------------------------------------------------------------------------