页面树结构

版本比较

标识

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

(此文档仅供参考)

原理

要通过 JDBC 驱动获取数据库中的表、视图等对象信息,核心是利用 JDBC 规范中定义的数据库元数据(Database Metadata) 机制,具体流程如下:

...

简言之,JDBC 驱动通过封装数据库底层的元数据查询逻辑,向上提供统一的DatabaseMetaData接口,开发者无需关注不同数据库的内部实现差异,只需调用标准方法即可便捷地获取表、视图等对象信息。这一机制体现了 JDBC “面向接口编程” 的设计思想,保证了数据库操作的跨平台性。

使用方法

1.下载JdbcTableLoader.java文件(md5hash:dd071f3d53f752a9afe24f45721f096d),放到服务器上,使用javac JdbcTableLoader.java编译成JdbcTableLoader.class文件。如果服务器没有javac工具,可以下载编译后的JdbcTableLoader.class文件(md5sum:37e597df1f420d3875f4037a3ac92d89)。

Image Removed

View file
nameJdbcTableLoader.class
height250
View file
nameJdbcTableLoader.java
height250

class文件(jdk8以上版本,md5sum:37e597df1f420d3875f4037a3ac92d89),放到BI所在服务器上

文件:JdbcTableLoader.class

2.下载config.properties文件,放于JdbcTableLoader.java相同目录,将数据库信息填写到文件中。

Image Removed View filename文件:config.properties

height配置说明如下:

250Image Added

3.执行java JdbcTableLoader命令查看结果

源代码文件如下(md5hash:dd071f3d53f752a9afe24f45721f096d),也可下载源代码文件手动编译后执行。

文件:JdbcTableLoader.java

代码示例

代码块
languagejava
titleJdbcTableLoader.java
collapsetrue
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.sql.Driver;

/**
 * JDBC驱动加载器和表信息获取器
 */
public class JdbcTableLoader implements AutoCloseable {
    
    private Properties config;
    private Connection connection;
    private Class driverClass;
    
    public JdbcTableLoader(String configFile) throws IOException {
        loadConfig(configFile);
    }
    
    /**
     * 加载配置文件
     */
    private void loadConfig(String configFile) throws IOException {
        System.out.println("加载配置文件: " + new File(configFile).getAbsolutePath());
        config = new Properties();
        try (FileInputStream fis = new FileInputStream(configFile)) {
            config.load(fis);
        }
    }
    
    /**
     * 加载JDBC驱动
     */
    public void loadDriver() throws Throwable {
        String libDir = config.getProperty("jdbc.lib.dir");
        String driverClassName = config.getProperty("jdbc.driver.class");
        
        // 加载lib目录下的所有jar包
        File libFolder = new File(libDir);
        if (!libFolder.exists() || !libFolder.isDirectory()) {
            throw new RuntimeException("驱动目录不存在: " + libDir);
        }
        
        List<URL> urls = new ArrayList<>();
        File[] jarFiles = libFolder.listFiles((dir, name) -> name.endsWith(".jar"));
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                urls.add(jarFile.toURI().toURL());
            }
        }
        
        // 创建类加载器并加载驱动
        URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]));
        // 某些驱动需要设置当前线程的类加载器
        Thread.currentThread().setContextClassLoader(classLoader);
        driverClass =  classLoader.loadClass(driverClassName);
        System.out.println("JDBC驱动加载成功: " + driverClass);
    }
    
    /**
     * 建立数据库连接
     */
    public void connect() throws Throwable {
        String url = config.getProperty("jdbc.url");
        String username = config.getProperty("jdbc.username");
        String password = config.getProperty("jdbc.password");
        Properties info = new Properties();
        info.put("user", username);
        info.put("password", password);
        connection = ((Driver) driverClass.getConstructor().newInstance()).connect(url, info);
        System.out.println("数据库连接成功");
    }
    
    /**
     * 获取指定catalog和schema的表信息
     */
    public List<String> getTables() throws Exception {
        String catalog = config.getProperty("jdbc.catalog");
        String schema = config.getProperty("jdbc.schema");
        String tableTypes = config.getProperty("jdbc.table.types");
        System.out.println("catalog: " + catalog);
        System.out.println("schema: " + schema);
        System.out.println("tableTypes: " + tableTypes);
        if (tableTypes == null || tableTypes.isEmpty()) {
            tableTypes = "TABLE,VIEW,MATERIALIZED QUERY TABLE,SYNONYM,ALIAS,EXTERNAL TABLE";
        }
        String tableMaxString = config.getProperty("jdbc.table.max");
        int maxTableCount = 100;
        try {   
            maxTableCount = Integer.parseInt(tableMaxString);
        } catch (NumberFormatException e) {
            // 默认100
        }
        
        List<String> tables = new ArrayList<>();
        DatabaseMetaData metaData = connection.getMetaData();
        
        try (ResultSet rs = metaData.getTables(catalog, schema, "%", tableTypes.split(","))) {
            int count = 0;
            while (rs.next()) {
                if (count >= maxTableCount) {
                    break;
                }
                count++;
                String tableName = rs.getString("TABLE_NAME");
                tables.add(tableName);
                System.out.println("发现表: " + tableName);
            }
        }
        
        return tables;
    }
    
    /**
     * 关闭连接
     */
    @Override
    public void close() {
        if (connection != null) {
            try {
                connection.close();
                System.out.println("数据库连接已关闭");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 主方法,用于测试
     */
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        try (JdbcTableLoader loader = new JdbcTableLoader("config.properties")) {
            loader.loadDriver();
            loader.connect();
            List<String> tables = loader.getTables();
            System.out.println("展示 " + tables.size() + " 个表");
            long end = System.currentTimeMillis();
            System.out.println("耗时: " + (end - start) + " 毫秒");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
} 

...