HikariCP 抽取方法&分页


HikariCP 参数化查询的方法已经知道了,将demo中的sql语句和参数抽离出来就形成了公用的方法了。
新增
public static int add(String sql, List<Object> params) { int result = -1; try { HikariDataSource dataSource = getDataSource(); Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); if (params != null) { for (int i = 0; i < params.size(); i++) { statement.setObject(i + 1, params.get(i)); } } statement.execute(); ResultSet resultSet = statement.getGeneratedKeys(); if (resultSet != null) { if (resultSet.next()) result = resultSet.getInt(1); } if (connection != null && !connection.isClosed()) connection.close(); if (dataSource != null && !dataSource.isClosed()) dataSource.close(); } catch (Exception e) { e.printStackTrace(); } return result; }
更新
public static int update(String sql,List<Object> params) { try { HikariDataSource dataSource = getDataSource(); Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(sql); if (params != null) { for (int i = 0; i < params.size(); i++) { statement.setObject(i + 1, params.get(i)); } } return statement.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } return -1; }
查询
public static <T> List<T> query(String sql, List<Object> params, Class<T> type) { try { /* HikariDataSource 是需要关闭的 */ HikariDataSource dataSource = getDataSource(); Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(sql); if (params != null) { for (int i = 0; i < params.size(); i++) { statement.setObject(i + 1, params.get(i)); } } ResultSet resultSet = statement.executeQuery(); List<T> list = ResultSetHelper.toList(resultSet, type); if (connection != null && !connection.isClosed()) connection.close(); if (dataSource != null && !dataSource.isClosed()) dataSource.close(); return list; } catch (Exception e) { e.printStackTrace(); } return null; }
转化方法
public class ResultSetHelper { public static <T> List<T> toList(ResultSet resultSet, Class<T> type) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException { List<T> list = new ArrayList<T>(); if (resultSet != null) { ResultSetMetaData md = resultSet.getMetaData();// 获取键名 int columnCount = md.getColumnCount();// 获取行的数量 while (resultSet.next()) { // 此类要有默认的构造函数 T instance = type.newInstance(); Field[] fields = type.getDeclaredFields(); for (int i = 1; i <= columnCount; i++) { String colName = md.getColumnName(i); Object val = resultSet.getObject(i); for (Field field : fields) { if (field.getName().equalsIgnoreCase(colName)) { field.setAccessible(true); field.set(instance, val); } } } list.add(instance); } } return list; } }
分页
分页其实是执行了两个SQL语句,一个查询SQL,一个统计SQL,且分页返回的也不只是一个 List<T>,而且还要包含 总数量 totalCount 和 总页数 totalPage
在实现分页的过程中,要分别执行 select 语句和 count 语句,
而执行 count 语句,直接获取执行结果的方法没有,即类似于 executeScalar 这样的方法,
只能是封装一个 返回 ResultSet 的方法,把 ResultSet 的第一行的第一个格子 返回去。
我们先创建一个类来代表分页方法的返回结果
public class PageResult<T> { private List<T> data; private int totalCount; private int totalPage; public List<T> getData() { return data; } public void setData(List<T> data) { this.data = data; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getTotalPage() { return this.totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } }
而分页方法应该像这个样子
PageResult<T> queryPage(String sql, List<Object> params, int currentPage, int pageSize, Class<T> type)
其内部我们需要通过参数来构成两个SQL语句。
public static <T> PageResult<T> queryPage(String sql, List<Object> params, int currentPage, int pageSize, Class<T> type) { PageResult<T> result = new PageResult<T>(); int startIndex = (currentPage - 1) * pageSize; String querySql = MessageFormat.format("{0} limit {1},{2}", sql, startIndex, pageSize); List<T> models = SQLHelper.query(querySql, params, type); result.setData(models); // 或正则,将select 和 from 中间的字符串替换成 count(0); String countSql = MessageFormat.format("select count(0) from ({0})t ", sql); String countStr = SQLHelper.executeScalar(countSql, params); int countVal = 0; if (!isBlank(countStr)) countVal = Integer.parseInt(countStr); int totalPage = (int) ((countVal + pageSize - 1) / pageSize); result.setTotalCount(countVal); result.setTotalPage(totalPage); return result; } private static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(str.charAt(i)) == false) { return false; } } return true; } public static String executeScalar(String sql, List<Object> params) { String result = null; try { /* HikariDataSource 是需要关闭的 */ HikariDataSource dataSource = getDataSource(); Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(sql); if (params != null) { for (int i = 0; i < params.size(); i++) { statement.setObject(i + 1, params.get(i)); } } ResultSet resultSet = statement.executeQuery(); if(resultSet!=null && resultSet.next()) result = resultSet.getString(1); if (connection != null && !connection.isClosed()) connection.close(); if (dataSource != null && !dataSource.isClosed()) dataSource.close(); } catch (Exception e) { e.printStackTrace(); } return result; }
公共的一个方法
private static HikariDataSource getDataSource() throws SQLException { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/javablog?useUnicode=true&characterEncoding=utf8&useSSL=false"); config.setUsername("root"); config.setPassword("123456"); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); return new HikariDataSource(config); }
最终把上面所有方法放入一个 SQLHelper 类中就构成了一个简单的 数据库访问类了。
版权说明
作者:SQBER
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
{0}
{5}
{1}
{2}回复
{4}
*昵称:
*邮箱:
个人站点:
*想说的话: