我的问题大致是这样的,但有点不同。我正在使用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/