对于那些想要将结果集打印为 util 类的更好版本的人
这对于打印结果集非常有帮助,并且可以通过单个 util 执行许多操作...感谢 Hami Torun!
在这个类中printResultSet 以通用方式使用ResultSetMetaData 看看它..
导入java.sql.*;
导入 java.util.ArrayList;
导入 java.util.List;
导入 java.util.StringJoiner;
公共最终类 DBTablePrinter {
/**
*
CHAR、
VARCHAR 的列类型类别
* 和类似的文本列。
*/
公共静态最终 int CATEGORY_STRING = 1;
/**
*
TINYINT,
SMALLINT 的列类型类别,
*
INT 和
BIGINT 列。
*/
公共静态最终 int CATEGORY_INTEGER = 2;
/**
*
REAL、
DOUBLE 的列类型类别,
* 和
DECIMAL 列。
*/
公共静态最终 int CATEGORY_DOUBLE = 3;
/**
* 日期和时间相关列的列类型类别,例如
*
DATE、
TIME、
TIMESTAMP 等。
*/
公共静态最终 int CATEGORY_DATETIME = 4;
/**
*
BOOLEAN 列的列类型类别。
*/
公共静态最终 int CATEGORY_BOOLEAN = 5;
/**
* 类型名称的类型的列类型类别
* 将被打印而不是内容,例如
BLOB,
*
BINARY、
ARRAY 等。
*/
公共静态最终 int CATEGORY_OTHER = 0;
/**
* 默认查询和打印的最大行数。
*/
私有静态最终 int DEFAULT_MAX_ROWS = 10;
/**
* 文本列的默认最大宽度
*(如
VARCHAR)列。
*/
私有静态最终 int DEFAULT_MAX_TEXT_COL_WIDTH = 150;
/**
* 从表
tableName 打印行的重载方法
* 使用给定的数据库连接进行标准输出
*
conn。总行数将被限制为
* {@link #DEFAULT_MAX_ROWS} 和
* {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将用于限制
* 文本列的宽度(如
VARCHAR 列)。
*
* @param conn 数据库连接对象 (java.sql.Connection)
* @param tableName 数据库表的名称
*/
公共静态无效打印表(连接连接,字符串表名){
printTable(conn, tableName, DEFAULT_MAX_ROWS, DEFAULT_MAX_TEXT_COL_WIDTH);
}
/**
* 从表
tableName 打印行的重载方法
* 使用给定的数据库连接进行标准输出
*
conn。总行数将被限制为
*
maxRows 和
* {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将用于限制
* 文本列的宽度(如
VARCHAR 列)。
*
* @param conn 数据库连接对象 (java.sql.Connection)
* @param tableName 数据库表的名称
* @param maxRows 最大数量。要查询和打印的行
*/
公共静态无效打印表(连接连接,字符串表名,int maxRows){
printTable(conn, tableName, maxRows, DEFAULT_MAX_TEXT_COL_WIDTH);
}
/**
* 从表
tableName 打印行的重载方法
* 使用给定的数据库连接进行标准输出
*
conn。总行数将被限制为
*
maxRows 和
*
maxStringColWidth 将用于限制
* 文本列的宽度(如
VARCHAR 列)。
*
* @param conn 数据库连接对象 (java.sql.Connection)
* @param tableName 数据库表的名称
* @param maxRows 最大数量。要查询和打印的行
* @param maxStringColWidth 最大值。文本列的宽度
*/
公共静态无效打印表(连接连接,字符串表名,int maxRows,int maxStringColWidth){
if (conn == null) {
System.err.println("DBTablePrinter 错误:没有连接到数据库(连接为空)!");
返回;
}
if (tableName == null) {
System.err.println("DBTablePrinter 错误:没有表名(tableName 为空)!");
返回;
}
if (tableName.length() == 0) {
System.err.println("DBTablePrinter 错误:空表名!");
返回;
}
如果(最大行数
* 使用 {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将结果集标准输出
* 限制文本列的宽度。
*
* @param rs
ResultSet 打印
*/
公共静态无效打印结果集(结果集rs){
printResultSet(rs, DEFAULT_MAX_TEXT_COL_WIDTH);
}
/**
* 打印行的重载方法
* ResultSet 使用
maxStringColWidth 标准输出
* 限制文本列的宽度。
*
* @param rs
ResultSet 打印
* @param maxStringColWidth 最大值。文本列的宽度
*/
公共静态无效打印结果集(结果集rs,int maxStringColWidth){
尝试 {
如果(rs == null){
System.err.println("DBTablePrinter 错误:结果集为空!");
返回;
}
如果(rs.isClosed()){
System.err.println("DBTablePrinter 错误:结果集已关闭!");
返回;
}
if (maxStringColWidth columns = new ArrayList(columnCount);
// 表名列表。如果它是连接的,则可以是多个
// 表查询
列出 tableNames = new ArrayList(columnCount);
// 获取列及其元数据。
// 注意: rsmd.getXXX 方法的 columnIndex 开始于 1 而不是 0
for (int i = 1; i maxStringColWidth) {
value = value.substring(0, maxStringColWidth - 3) + "...";
}
休息;
}
// 调整列宽
c.setWidth(value.length() > c.getWidth() ? value.length() : c.getWidth());
c.addValue(值);
} // for 循环 columnCount 结束
行数++;
} // while 结束 (rs.next)
/*
至此我们已经遍历元数据,得到
columns 并创建了所有 Column 对象,迭代
ResultSet 行,填充列值并调整
列宽。
我们还不能开始打印,因为我们必须准备
行分隔符字符串。
*/
// 为了好玩,我将使用 StringBuilder
StringBuilder strToPrint = new StringBuilder();
StringBuilder rowSeparator = new StringBuilder();
/*
准备要打印的列标签以及行分隔符。
它应该看起来像这样:
+--------+------------+------------+-----------+(行分隔器)
| EMP_NO |出生日期 | FIRST_NAME | LAST_NAME | (标签行)
+--------+------------+------------+-----------+(行分隔器)
*/
// 遍历列
对于(C列:列){
int 宽度 = c.getWidth();
// 将列标签居中
打印字符串;
字符串名称 = c.getLabel();
int diff = 宽度 - name.length();
如果((差异%2)== 1){
// diff 不能被 2 整除,宽度加 1(和 diff)
// 这样我们就可以在左右两边有相等的填充
// 列标签。
宽度++;
差异++;
c.setWidth(宽度);
}
int paddingSize = diff / 2; // InteliJ 说强制转换为 int 是多余的。
// 感谢 stackoverflow.com 上的 user102008 的酷字符串中继器代码
字符串填充 = new String(new char[paddingSize]).replace("\0", "");
toPrint = "|" + 填充 + 名称 + 填充 + " ";
// END 居中列标签
strToPrint.append(toPrint);
rowSeparator.append("+");
rowSeparator.append(new String(new char[width + 2]).replace("\0", "-"));
}
字符串 lineSeparator = System.getProperty("line.separator");
// 这真的有必要吗?
lineSeparator = lineSeparator == null ? "\n" : 行分隔符;
rowSeparator.append("+").append(lineSeparator);
strToPrint.append("|").append(lineSeparator);
strToPrint.insert(0, rowSeparator);
strToPrint.append(rowSeparator);
StringJoiner sj = new StringJoiner(", ");
对于(字符串名称:tableNames){
sj.add(名称);
}
字符串信息 = "打印" + rowCount;
信息 += 行数 > 1 ? " 来自 " 的行 : " 来自 " 的行;
信息 += tableNames.size() > 1 ? “表”:“表”;
信息 += sj.toString();
System.out.println(info);
// 打印出格式化的列标签
System.out.print(strToPrint.toString());
字符串格式;
// 打印行
对于 (int i = 0; 我
* 整数不应被截断,因此列宽应
* 可以在没有列宽限制的情况下进行调整。文本列应该是
* 左对齐,可以截断到最大值。列宽等...
*
* 也可以看看:
* java.sql.Types
*
* @param type 通用 SQL 类型
* @return 该类型所属的类别
*/
私有静态 int whichCategory(int type) {
开关(类型){
案例类型.BIGINT:
案例类型.TINYINT:
案例类型.SMALLINT:
案例类型.INTEGER:
返回类别整数;
案例类型.REAL:
案例类型.DOUBLE:
案例类型。十进制:
返回 CATEGORY_DOUBLE;
案例类型。日期:
案例类型。时间:
案例类型.TIME_WITH_TIMEZONE:
案例类型.TIMESTAMP:
案例类型.TIMESTAMP_WITH_TIMEZONE:
返回类别日期时间;
案例类型。布尔值:
返回 CATEGORY_BOOLEAN;
案例类型.VARCHAR:
案例类型.NVARCHAR:
案例类型.LONGVARCHAR:
案例类型.LONGNVARCHAR:
案例类型.CHAR:
案例类型.NCHAR:
返回类别字符串;
默认:
返回 CATEGORY_OTHER;
}
}
/**
* 表示一个数据库表列。
*/
私有静态类列{
/**
* 列标签。
*/
私有字符串标签;
/**
* 定义的列的通用 SQL 类型
*
* java.sql.Types
* .
*/
私有 int 类型;
/**
* 定义的列的通用 SQL 类型名称
*
* java.sql.Types
* .
*/
私有字符串类型名;
/**
* 将根据列标签调整的列宽
* 和要打印的值。
*/
私人 int 宽度 = 0;
/**
* ResultSet 每一行的列值。
*/
私有列表值 = new ArrayList();
/**
* 使用String.format 进行文本对齐标记。
* 空字符串 ("") 证明正确,
* 破折号 (-) 左对齐。
*
* @see #justifyLeft()
*/
私人字符串 justifyFlag = "";
/**
* 列类型类别。列将根据
* 到它们的列类型和特定需要正确打印它们。
*/
私有 int typeCategory = 0;
/**
* 用列标签构造一个新的Column,
* 通用 SQL 类型和类型名称(定义见
*
* java.sql.Types
* )
*
* @param label 列标签或名称
* @param type 通用 SQL 类型
* @param typeName 通用 SQL 类型名称
*/
公共列(字符串标签,整数类型,字符串类型名称){
this.label = 标签;
this.type = 类型;
this.typeName = typeName;
}
/**
* 返回列标签
*
* @return 列标签
*/
公共字符串 getLabel() {
返回标签;
}
/**
* 返回列的通用 SQL 类型
*
* @return 通用 SQL 类型
*/
公共 int getType() {
返回类型;
}
/**
* 返回列的通用 SQL 类型名称
*
* @return 通用 SQL 类型名称
*/
公共字符串 getTypeName() {
返回类型名;
}
/**
* 返回列的宽度
*
* @return 列宽
*/
公共 int getWidth() {
返回宽度;
}
/**
* 设置列宽为width
*
* @param width 列的宽度
*/
公共无效setWidth(int宽度){
this.width = 宽度;
}
/**
* 添加String 表示 (value)
* 此列对象的 {@link #values} 列表的值。
* 这些值将来自 a 的每一行
*
* 结果集
* 数据库查询。
*
* @param value 要添加到 {@link #values} 的列值
*/
公共无效添加值(字符串值){
values.add(value);
}
/**
* 返回行索引i 处的列值。
* 注意索引从 0 开始,所以getValue(0)
* 将从第一行获取该列的值
* 一个
* 结果集。
*
* @param i 要获取的列值的索引
* @return 值的字符串表示形式
*/
公共字符串 getValue(int i) {
返回值.get(i);
}
/**
* 返回 {@link #justifyFlag} 的值。专栏
* 值将使用String.format 和
* 此标志将用于右对齐或左对齐文本。
*
* @return 此列的 {@link #justifyFlag}
* @see #justifyLeft()
*/
公共字符串 getJustifyFlag() {
返回正当化标志;
}
/**
* 将 {@link #justifyFlag} 设置为 "-" 以便
* 打印时列值将左对齐
*String.format。通常数字是正确的
* 对齐,文本将左对齐。
*/
公共无效justifyLeft(){
this.justifyFlag = "-";
}
/**
* 返回列的通用 SQL 类型类别
*
* @return 列的{@link #typeCategory}
*/
公共 int getTypeCategory() {
返回类型类别;
}
/**
* 设置列的{@link #typeCategory}
*
* @param typeCategory 类型类别
*/
公共无效 setTypeCategory(int typeCategory) {
this.typeCategory = typeCategory;
}
}
}
这是执行此操作的 scala 版本...它将以通用方式打印列名和数据...
def printQuery(res: ResultSet): Unit = {
val rsmd = res.getMetaData
val columnCount = rsmd.getColumnCount
var rowCnt = 0
val s = StringBuilder.newBuilder
while (res.next()) {
s.clear()
if (rowCnt == 0) {
s.append("| ")
for (i <- 1 to columnCount) {
val name = rsmd.getColumnName(i)
s.append(name)
s.append("| ")
}
s.append("\n")
}
rowCnt += 1
s.append("| ")
for (i <- 1 to columnCount) {
if (i > 1)
s.append(" | ")
s.append(res.getString(i))
}
s.append(" |")
System.out.println(s)
}
System.out.println(s"TOTAL: $rowCnt rows")
}