Java JDBC 2

Connection

与特定数据库的一个连接(会话),执行SQL语句并在连接的上下文中返回结果。

  • 数据库信息
// 数据库元信息包括:数据库表、SQL语法、存储过程、连接的功能等。
DatabaseMetaData getMetaData();
  • 连接属性
// 自动提交:默认是
// 自动提交时,所有SQL都以单个事务执行和提交;
//     语句完成时进行提交,完成的时机取决于语句类型:
//     DML语句:完成执行时提交事务
//     Select语句:ResultSet关闭时提交
//     CallableStatement:所有ResultSet关闭、所有更新数和输出参数检索完
// 非自动提交时,多个SQL组成一个事务,显式提交或回滚事务。
boolean getAutoCommit();
void setAutoCommit(boolean autoCommit);

// 只读:
boolean isReadOnly();
// 此方法不能在事务中调用
void setReadOnly(boolean readOnly);

// ResultSet保持性
// ResultSet.HOLD_CURSORS_OVER_COMMIT 事务提交时ResultSet仍打开
// ResultSet.CLOSE_CURSORS_AT_COMMIT 事务提交时ResultSet关闭
int getHoldability();
void setHoldability(int holdability);

// 事务级别:
// Connection.TRANSACTION_NONE:0,无事务
// Connection.TRANSACTION_READ_UNCOMMITTED:1,未提交读
// Connection.TRANSACTION_READ_COMMITTED:2,已提交读
// Connection.TRANSACTION_REPEATABLE_READ:4,可重复读
// Connection.TRANSACTION_SERIALIZABLE:8,串行化
int getTransactionIsolation();
void setTransactionIsolation(int level);

  • 创建Statement
// resultSetType:
//     ResultSet.TYPE_FORWARD_ONLY
// resultSetConcurrency:
//     ResultSet.CONCUR_READ_ONLY
// holdability:
//     getHoldability()
Statement createStatement();

Statement createStatement(int resultSetType, int resultSetConcurrency);

// resultSetType: 
//     ResultSet.TYPE_FORWARD_ONLY
//     ResultSet.TYPE_SCROLL_INSENSITIVE
//     ResultSet.TYPE_SCROLL_SENSITIVE
// resultSetConcurrency:
//     ResultSet.CONCUR_READ_ONLY
//     ResultSet.CONCUR_UPDATABLE
// resultSetHoldability:
//     ResultSet.HOLD_CURSORS_OVER_COMMIT
//     ResultSet.CLOSE_CURSORS_AT_COMMIT
Statement createStatement(int resultSetType, int resultSetConcurrency, 
        int resultSetHoldability)
  • 创建PreparedStatement
PreparedStatement prepareStatement(String sql);
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency);
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, 
        int resultSetHoldability);

PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
PreparedStatement prepareStatement(String sql, int columnIndexes[]);
PreparedStatement prepareStatement(String sql, String columnNames[]);
  • 创建CallableStatement
CallableStatement prepareCall(String sql);
CallableStatement prepareCall(String sql, int resultSetType,int resultSetConcurrency);
CallableStatement prepareCall(String sql, int resultSetType,int resultSetConcurrency,
        int resultSetHoldability);
  • 事务
// 非自动提交时,使用此方法显式提交事务。
// 提交上次commit/rollback之后的所有更改,释放Connection持有的所有数据库锁
void commit();

// 非自动提交是,使用此方法回滚事务。
// 撤销上次commit/rollback之后的所有更改,释放Connection持有的所有数据库锁
void rollback();
  • 保存点
// 在当前事务中创建一个命名保存点
// 如果在事务外调用,则启动一个新事务
Savepoint setSavepoint(String name);
// 创建一个匿名保存点
Savepoint setSavepoint();

// 回滚到指定保存点(只在非自动提交时调用)
void rollback(Savepoint savepoint);

void releaseSavepoint(Savepoint savepoint);
  • 关闭连接
// 立即释放Connection持有的数据库和JDBC资源,而不是等待自动释放。
// 如果已关闭,调用此方法则无操作。
// 强烈建议在调用此方法前,显式调用commit或rollback方法。
void close();

// 查询连接是否关闭。
// 连接在调用close或发生特定错误时被关闭
// 此方法并不用来判断连接是否有效。典型的是通过捕获操作异常来判断连接失效。
boolean isClosed();

// 驱动发送查询语句或使用其他方式已检查连接是否有效
// 有效返回true,无效返回false,超时抛出异常
boolean isValid(int timeout);
  • 类型映射
Map> getTypeMap();
void setTypeMap(Map> map);

DatabaseMetaData

// 获取数据库
// 返回:ResultSet列
//     TABLE_CAT:String,数据库名
ResultSet getCatalogs();

// 获取表
// catalog:数据库,null表示不指定
// schemaPattern:表模式
// tableNamePattern:表名模式
// types:表类型,见TABLE_TYPE
// 返回:ResultSet列
//     TABLE_CAT:String,数据库名,可能为null
//     TABLE_SCHEM:String,表模式,可能为null
//     TABLE_NAME:String,表名
//     TABLE_TYPE:String,表类型,有TABLE,VIEW,SYSTEM TABLE,
//          GLOBAL TEMPORARY,LOCAL TEMPORARY,ALIAS,SYNONYM
//     REMARKS:String,表备注
ResultSet getTables(String catalog, String schemaPattern, 
        String tableNamePattern, String types[]);

// 获取列
// catalog:数据库,null表示不指定
// schemaPattern:表模式
// tableNamePattern:表名模式
// columnNamePattern:列名模式
// 返回:ResultSet列
//     TABLE_CAT:String,数据库名,可能为null
//     TABLE_SCHEM:String,表模式,可能为null
//     TABLE_NAME:String,表名
//     COLUMN_NAME:String,列名
//     DATA_TYPE:int,类型,见java.sql.Types
//     TYPE_NAME:String,类型名
//     COLUMN_SIZE:int,列大小
//     REMARKS:String,备注
//     COLUMN_DEF:String,默认值,可能为null
//     ORDINAL_POSITION:int,列顺序,1起
//     IS_NULLABLE:String:YES,可以保护NULL;NO,不能;空白,未知;
//     IS_AUTOINCREMENT:String:YES,自增;NO,不是;空白,未知;
ResultSet getColumns(String catalog, String schemaPattern, 
        String tableNamePattern, String columnNamePattern);

// 获取索引
// catalog:数据库,null表示不指定
// schema:表模式
// table:表名,不允许为null
// unique:唯一索引
// approximate:
// 返回:ResultSet列
//     TABLE_CAT:String,数据库名,可能为null
//     TABLE_SCHEM:String,表模式,可能为null
//     TABLE_NAME:String,表名
//     INDEX_NAME:String,索引名
//     NON_UNIQUE:boolean,是否不是唯一索引
//     COLUMN_NAME:String,索引列名
//     ORDINAL_POSITION:short,索引列名位置
ResultSet getIndexInfo(String catalog, String schema, String table,
        boolean unique, boolean approximate);

获取数据库表结构

  • 表结构Bean
public class Database {
    /** 数据库名 */
    private String databaseName;

    /** 表 */
    private Map tables = new LinkedHashMap<>();

    static class Table {
        /** 表名 */
        String tableName;
        /** 备注 */
        String comment;
        /** 列 */
        Map columns = new LinkedHashMap<>();
        /** 索引 */
        Map indexes = new LinkedHashMap<>();
    }

    static class Column {
        /** 列名 */
        String columnName;
        /** 类型,见java.sql.Types */
        int dataType;
        /** 类型名 */
        String typeName;
        /** 大小*/
        int columnSize;
        /** null,未知;true,yes;false,no;*/
        Boolean nullable;
        /** 默认值 */
        String defaultValue;
        /** null,未知;true,yes;false,no;*/
        Boolean autoIncrement;
        /** 备注 */
        String comment;
    }

    static class Index {
        /** 索引名 */
        private String indexName;
        /** 是否是唯一索引 */
        private boolean unique;
        /** 列名 */
        private List columnNames = new ArrayList<>();
    }

    // 打印表结构
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(databaseName + ": " + tables.size() + "\n\n");

        for (Table table : tables.values()) {
            sb.append("CREATE TABLE `" + table.tableName + "` (\n");

            for (Column column : table.columns.values()) {
                sb.append("    `" + column.columnName + "` " + column.typeName + "(" + column.columnSize + ")");
                if (column.nullable != null && !column.nullable) {
                    sb.append(" NOT NULL");
                }
                if (StringUtils.isNotBlank(column.defaultValue)) {
                    sb.append(" DEFAULT '" + column.defaultValue + "'");
                }
                if (column.autoIncrement != null && column.autoIncrement) {
                    sb.append(" AUTO_INCREMENT");
                }
                if (StringUtils.isNotBlank(column.comment)) {
                    sb.append(" COMMENT '" + column.comment + "'");
                }
                sb.append(",\n");
            }

            for (Index index : table.indexes.values()) {
                sb.append("    ");
                String indexName = index.indexName;
                if (StringUtils.equalsIgnoreCase(indexName, "PRIMARY")) {
                    sb.append("PRIMARY KEY");
                } else if (index.unique) {
                    sb.append("UNIQUE KEY `" + indexName + "`");
                } else {
                    sb.append("KEY `" + indexName + "`");
                }
                sb.append(" (");
                for (int j = 0; j < index.columnNames.size(); j++) {
                    String columnName = index.columnNames.get(j);
                    sb.append("`" + columnName + "`");
                    if (j != index.columnNames.size()-1) {
                        sb.append(", ");
                    }
                }
                sb.append("),\n");
            }

            // 去掉最后一行的“,”
            sb.replace(sb.length()-2, sb.length(), "\n)");

            if (StringUtils.isNotBlank(table.comment)) {
                sb.append(" COMMENT='" + table.comment + "'");
            }

            sb.append(";\n\n");
        }
        return sb.toString();
    }
}
  • 获取表结构
public static Map getDatabases(String url, String database, String table) {
    Map databaseMap = new HashMap<>();

    Connection connection = null;
    ResultSet resultSet = null;
    try {
        Properties info = new Properties();
        connection = DriverManager.getConnection(url, info);

        DatabaseMetaData metaData = connection.getMetaData();

        // Database
        {
            List databaseNames = new ArrayList<>();

            if (database != null) {
                databaseNames.add(database);
            } else {
                Set systemDatabases = new HashSet<>();
                // MySQL
                systemDatabases.add("information_schema");
                systemDatabases.add("performance_schema");

                resultSet = metaData.getCatalogs();
                while (resultSet.next()) {
                    String databaseName = resultSet.getString("TABLE_CAT");
                    if (!systemDatabases.contains(databaseName)) {
                        databaseNames.add(databaseName);
                    }
                }
                resultSet.close();
            }

            for (String databaseName : databaseNames) {
                databaseMap.put(database, new Database(databaseName));
            }
        }

        // Table
        {
            resultSet = metaData.getTables(null, null, table, new String[]{"TABLE"});
            while (resultSet.next()) {
                String databaseName = resultSet.getString("TABLE_CAT");

                String tableName = resultSet.getString("TABLE_NAME");

                // Type: TABLE, VIEW, SYSTEM TABLE, GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM
                // String tableType = resultSet.getString("TABLE_TYPE");
                
                String comment = resultSet.getString("REMARKS");

                databaseMap.get(databaseName).addTable(tableName, comment);
            }
            resultSet.close();
        }

        // Column
        {
            resultSet = metaData.getColumns(null, null, table, null);
            while (resultSet.next()) {
                String databaseName = resultSet.getString("TABLE_CAT");

                String tableName = resultSet.getString("TABLE_NAME");

                String columnName = resultSet.getString("COLUMN_NAME");

                // SQL type from java.sql.Types
                int dataType = resultSet.getInt("DATA_TYPE");

                // Data source dependent type name, for a UDT the type name is fully qualified
                String typeName = resultSet.getString("TYPE_NAME");

                int columnSize = resultSet.getInt("COLUMN_SIZE");

                String comment = resultSet.getString("REMARKS");

                // may be null
                String defaultValue = resultSet.getString("COLUMN_DEF");

                // YES: include NULLs
                // NO: not include NULLs
                // empty string: nullability is unknown
                String isNullable = resultSet.getString("IS_NULLABLE");
                Boolean nullable = null;
                if (StringUtils.equalsIgnoreCase(isNullable, "YES")) {
                    nullable = true;
                } else if (StringUtils.equalsIgnoreCase(isNullable, "NO")) {
                    nullable = false;
                }

                // YES: is auto incremented
                // NO: is not auto incremented
                // empty string: unknown
                String IS_AUTOINCREMENT = resultSet.getString("IS_AUTOINCREMENT");
                Boolean autoIncrement = null;
                if (StringUtils.equalsIgnoreCase(IS_AUTOINCREMENT, "YES")) {
                    autoIncrement = true;
                } else if (StringUtils.equalsIgnoreCase(IS_AUTOINCREMENT, "NO")) {
                    autoIncrement = false;
                }

                databaseMap.get(databaseName).addColumn(tableName, columnName, dataType, typeName, columnSize, nullable, defaultValue, autoIncrement, comment);
            }
            resultSet.close();
        }

        // Index
        {
            for (Database db : databaseMap.values()) {
                for (String tb : db.getTableNames()) {
                    resultSet = metaData.getIndexInfo(db.getDatabaseName(), null, tb, false, false);
                    while (resultSet.next()) {
                        String databaseName = resultSet.getString("TABLE_CAT");

                        String tableName = resultSet.getString("TABLE_NAME");

                        String indexName = resultSet.getString("INDEX_NAME");

                        boolean unique = !resultSet.getBoolean("NON_UNIQUE");

                        String columnName = resultSet.getString("COLUMN_NAME");

                        databaseMap.get(databaseName).addIndex(tableName, indexName, unique, columnName);
                    }
                    resultSet.close();
                }
            }
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    return databaseMap;
}
  • 测试
public static void main(String[] args) {
    String url = "jdbc:mysql://localhost:3306/test?user=root&password=123456&useUnicode=true&characterEncoding=UTF-8";
    Map databaseMap = SchemaUtil.getDatabases(url, "test", "user");
    for (Database database : databaseMap.values()) {
       System.out.println(database);
   }
}

结果:

test: 1

CREATE TABLE `user` (
    `id` BIGINT(19) NOT NULL AUTO_INCREMENT,
    `userName` VARCHAR(128) NOT NULL COMMENT '账号',
    `nickName` VARCHAR(100) NOT NULL,
    `status` TINYINT(3) DEFAULT '0',
    `createTime` BIGINT(19) NOT NULL,
    `updateTime` BIGINT(19) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `u_s` (`userName`, `status`),
    KEY `key_un` (`userName`)
);

你可能感兴趣的:(Java JDBC 2)