我的问题大致是这样的,但有点不同。我正在使用java中的以下代码检索表的主键:

DatabaseMetaData meta = connection.getMetaData();
ResultSet rs = meta.getPrimaryKeys(null, null, "global_settings");
while (rs.next()) {
     System.out.println(rs.getString("COLUMN_NAME"));
}

表global_settings只有一个主键列,即global_setting_id。
但是,循环似乎运行了四次,输出是:
global_setting_id
global_setting_id
global_setting_id
global_setting_id

但是,对于具有组合键的表,循环可以正常工作,例如,对于具有构成组合主键的三列(用户id、国家id、税收id)的表user_info,
循环提供的输出为:
user_id
national_id
taxation_id

我正在使用mysql,驱动程序是
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.18</version>
</dependency>

这有点微不足道,但仍然是我在做的一项任务。这是一个错误还是我这边的问题?

最佳答案

所以,在放弃了一段时间后,我在尝试其他东西时无意中遇到了这个问题。背景是我有四个数据库,其中一些表共享相同的表名,如用户帐户、全局设置等。
我发现的问题是:
我没有在

   getPrimaryKeys(catalog, schema, table_name)

正确的方法是
   getPrimaryKeys("my_database", null, "my_table")

我没有指定数据库的原因是我认为连接字符串,即。
DriverManager.getConnection("jdbc:mysql://localhost:3306/my_database?..."

使操作非常特定于指定的数据库。
我没有注意到documentation所说的:
目录-目录名;存储时必须与目录名匹配
在数据库中;“”检索那些没有目录的;空表示
目录名不应用于缩小搜索范围
与我连接的用户拥有其他四个数据库的所有权限。这意味着,不指定我连接的数据库允许“入侵”从用户也可以访问的其他数据库中的表中获取主键列。正如我刚才所解释的,我不知道单一的数据库连接允许这样的“入侵”操作。
现在,您可能想知道为什么我不能指定数据库并停止在那里。嗯,这个项目的结构是这样的,我使用同一个程序,根据访问的组织数据库来切换连接,方法是使用组织id从主数据库中获取连接字符串。我错过的是从master数据库的connections表中获取组织数据库名称。
所以这是我为得出这个结论而执行的测试用例:
创建两个smu教师数据库,smu农民数据库;
创建表用户帐户,但在每个数据库中使用不同的主键名,即。
中小学教师
   CREATE TABLE `user_accounts` (
         `user_id` int(11) NOT NULL AUTO_INCREMENT,
         `username` varchar(50) NOT NULL,
         `surname` varchar(50) NOT NULL,
         `first_name` varchar(50) DEFAULT NULL,
          PRIMARY KEY (`user_id`,`username`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

为蓝精灵农民
   CREATE TABLE `user_accounts` (
       `user_identity` int(11) NOT NULL AUTO_INCREMENT,
       `username` varchar(50) NOT NULL,
       `surname` varchar(50) NOT NULL,
       `first_name` varchar(50) DEFAULT NULL,
       PRIMARY KEY (`user_identity`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

创建一个对任何数据库都具有所有权限的用户,从smu根用户开始
   GRANT ALL PRIVILEGES ON `smu_%`.* TO `smu_root`@`%`

创建一个只对一个数据库具有所有权限的用户smu-teachers,即用户smu-teachers
   GRANT ALL PRIVILEGES ON `smu_teachers`.* TO `smu_teachers_user`@`%`

使用用户smu_root运行测试程序:
@Test
public void getPrimaryKeys() throws Exception {
    DatabaseMetaData databaseMetaData = null;
    ResultSet rs = null;
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/smu_teachers_corp?" +
                    "autoReconnect=true&allowMultiQueries=true&useSSL=false&createDatabaseIfNotExist=false&allowPublicKeyRetrieval=true",
            "smu_root", "smu_root_password");
    try {
        databaseMetaData = connection.getMetaData();
        rs = databaseMetaData.getPrimaryKeys(null, null, "user_accounts");
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        while (rs.next()) {
            System.out.println(rs.getString("COLUMN_NAME"));
            for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
                System.out.println("Label: " + resultSetMetaData.getColumnLabel(i) + "  Value:" + rs.getString(i));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出:
user_identity
Label: TABLE_CAT  Value:smu_farmers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:user_identity
Label: KEY_SEQ  Value:1
Label: PK_NAME  Value:PRIMARY
user_id
Label: TABLE_CAT  Value:smu_teachers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:user_id
Label: KEY_SEQ  Value:1
Label: PK_NAME  Value:PRIMARY
username
Label: TABLE_CAT  Value:smu_teachers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:username
Label: KEY_SEQ  Value:2
Label: PK_NAME  Value:PRIMARY

使用用户smuêu root运行测试程序,但指定数据库名称,例如smuêu farmers产量:
user_identity
Label: TABLE_CAT  Value:smu_farmers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:user_identity
Label: KEY_SEQ  Value:1
Label: PK_NAME  Value:PRIMARY

在指定和不指定数据库名称的情况下,与用户smu_teachers一起运行测试程序会产生以下结果:
user_id
Label: TABLE_CAT  Value:smu_teachers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:user_id
Label: KEY_SEQ  Value:1
Label: PK_NAME  Value:PRIMARY
username
Label: TABLE_CAT  Value:smu_teachers
Label: TABLE_SCHEM  Value:null
Label: TABLE_NAME  Value:user_accounts
Label: COLUMN_NAME  Value:username
Label: KEY_SEQ  Value:2
Label: PK_NAME  Value:PRIMARY

如果其他人也面临类似的问题,这可以帮助他们轻松判断自己做错了什么。

关于java - 当键为单个时,metaData.getPrimaryKeys()返回四个相同的记录,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58726298/

10-11 22:31