文章目录
- 前提
- 1.准备数据
- 1.1 建表语句
- 1.2 插入数据
- 2.程序代码
- 3.返回结果与分析
- 4.验证
前提
获取h_user表中count(*)字段的值打印出来,打印出来是0,数据库中执行sql返回不是0。端点调试找到原因。下面先把数据库表数据及程序贴出来。
1.准备数据
1.1 建表语句
CREATE TABLE public.h_user (id serial4 not null,username varchar(50) NULL,"password" varchar(64) NULL,nickname varchar(60) NULL,email varchar(255) NULL,gender bit(1) NULL,height float4 NULL,CONSTRAINT user_pkey PRIMARY KEY (id)
);
1.2 插入数据
INSERT INTO public.h_user (username,"password",nickname,email,gender,height) VALUES ('ztttest','ztttest1234','ztt','5938@qq','0',173.0);
2.程序代码
程序入口:countTst的main方法
package org.example.countTest;
import java.util.List;
public class countTst {public static void main(String[] args) throws Exception {int sumCount =0;String countSql = "select count(*) totalcnt from h_user ";JdbcUtils jdbcUtils = new JdbcUtils("jdbc:postgresql://localhost:5432/postgres?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false","postgres","postgres");List<TotalRecord> totalNumList = jdbcUtils.executeQuery(countSql, TotalRecord.class,null);if(totalNumList.size()>0){// 获取表总行数sumCount = totalNumList.get(0).getTotalcnt();System.out.println("总数sumCount为:"+sumCount);}}
}
实体类:TotalRecord
package org.example.countTest;
public class TotalRecord {private int totalcnt;public int getTotalcnt() {return totalcnt;}public void setTotalcnt(int totalcnt) {this.totalcnt = totalcnt;}
}
工具类 JdbcUtils
package org.example.countTest;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class JdbcUtils {private String url;public JdbcUtils(String url, String username, String password) {this.url = url;this.username = username;this.password = password;}private String username;private String password;public static Connection conn = null;public static PreparedStatement ps = null;/*** 数据库列与实体对象映射处理* @param sql* @param clazz* @param parameters* @param <T>* @return* @throws Exception*/public <T> List<T> executeQuery(String sql, Class clazz, Object...parameters) throws Exception {// 获取连接conn = getConnection();// 执行SQL获取结果集ResultSet rs = executeQuery(sql, parameters);// 获取表的元数据ResultSetMetaData metaData = ps.getMetaData();List<T> resultList = new ArrayList<>();// 结果集映射成对象实体while(rs.next()) {// 获取表字段总数int columnCount = metaData.getColumnCount();// 通过反射实例化对象Object obj = clazz.newInstance();// 遍历表字段for (int i = 1; i <= columnCount; i++) {// 列名String columnName = metaData.getColumnName(i);// 列值Object columnValue = rs.getObject(i);// 数据库字段与数据库值的映射setFieldValueForColumn(obj, columnName, columnValue);}resultList.add((T) obj);}// 关闭资源JdbcUtils.close(JdbcUtils.conn, JdbcUtils.ps, rs);return resultList;}/*** 根据字段名称设置对象属性* @param o* @param columnName* @param columnValue*/private static void setFieldValueForColumn(Object o, String columnName, Object columnValue) {Class<?> aClass = o.getClass();try {Field field = aClass.getDeclaredField(columnName);field.setAccessible(true);field.set(o, columnValue);field.setAccessible(false);} catch (Exception e) {// 驼峰模式的处理if (columnName.contains("_")) {// \w -> 元字符,相当于 [a-zA-Z0-9]Pattern pattern = Pattern.compile("_(\\w)");columnName = columnName.toLowerCase();Matcher matcher = pattern.matcher(columnName);StringBuffer sb = new StringBuffer();if (matcher.find()) {// matcher.group(1) 指的是第一个括号里的东西 \w// 替换掉_,并将_的相邻下一个字母转为大写matcher.appendReplacement(sb, matcher.group(1).toUpperCase());}matcher.appendTail(sb);// 再次调用复制操作setFieldValueForColumn(o,sb.toString(),columnValue);}}}/*** 执行查询* @param sql* @param parameters* @return*/public ResultSet executeQuery(String sql, Object...parameters) throws SQLException {ResultSet rs = null;// 获取数据库库连接conn = getConnection();// 创建Statement对象ps = conn.prepareStatement(sql);// 设置sql中的参数if (Objects.nonNull(parameters) && parameters.length > 0) {for (int i = 0; i < parameters.length; i++) {ps.setObject(i+1, parameters[i]);}}// 返回结果集return ps.executeQuery();}/*** 数据库连接* @return* @throws SQLException*/public Connection getConnection() throws SQLException {if (conn == null) {try {conn = DriverManager.getConnection(url, username, password);} catch (SQLException e) {e.printStackTrace();}}return conn;}public static void close(Connection conn, Statement sta, ResultSet rs){try{// 关闭ResultSetif(Objects.nonNull(rs)){rs.close();}// 关闭Statementif (Objects.nonNull(sta)) {sta.close();}// 关闭Connectionif (Objects.nonNull(conn)) {sta.close();}}catch (Exception e){e.printStackTrace();}}
}
3.返回结果与分析
程序跑的结果如下:
数据库中执行sql的结果:
ResultSet rs中执行完获取时还可以获取到数据。接着进setFieldValueForColumn(obj, columnName, columnValue)方法中看。
执行 field.set(o, columnValue);时抛异常“不能设置int字段org.example.countTest.TotalRecord.totalcnt为java.lang.Long。”
原因找到了,count(*)返回的是Long类型的数据,我们的实体类TotalRecord 中属性 totalcnt的数据类型是int,所以接收数据时抛异常了,把相对应的totalcnt改为long类型,并把countTst中的main方法中sumCount局部变量改为long就可以接收到数据了。