我必须处理 Java 以创建一个 Restful API,我将它与 MySQL 一起使用来查询数据库。
我是 Java 的新手,这可能是一个非常基本的问题,但习惯了不存在此问题的 PHP 框架,我想知道在 Java 中有什么方法可以做到这一点。
我正在查询通过外键连接它们的 3 个表,我发现如果其中两个表具有相同的列名,则只会返回其中一个。 from
语句中声明的最新表中的一个。似乎他们被覆盖了。
例如,如果表 type_application
和 type_leaves
都有一个 name
列,则只有 name
列from type_leaves
将在此查询中返回:
select * from leaves, type_applications, type_leaves
where leaves.type_leave = type_leaves.id and
leaves.type_application = type_applications.id;
现在,我知道这可以通过指定所有需要的列名并以表名作为前缀(以防它们重复)并使用 as
创建别名来轻松解决:
select leaves.id, type_leaves.name as leaves_name, type_applications.name as application_name
from leaves, type_applications, type_leaves
where leaves.type_leave = type_leaves.id and
leaves.type_application = type_applications.id;
但这听起来不是我的最佳解决方案。我宁愿继续使用 *
来获取所有字段(这是我一直想要的)。
这也有助于实现更小的查询、更易于阅读和更易于维护,以防我不断地在表中添加或删除列。
有什么解决办法吗?在Java中有什么处理方式?
最佳答案
我也是 Java 的新手,所以我听到你的声音 ;)。但在我尽力给你答案之前,如果你不介意的话,我想说一句话。您的问题与 Java 和数据库/SQL 有关。您提供了一些 SQL,它解释了关于您的数据库表的一些事情以及您可以从查询中得到什么。但是您的主要问题是 Java,您没有提供任何 Java 代码,以便我们可以更好地了解您要完成的工作以及您遇到问题的确切位置。话虽如此,我希望以下内容能让您了解您可以做什么:
首先,查询中的 ResultSet
包含两个 name
列。它们不会被覆盖。这是一个例子:
String sql = "select * from leaves, type_applications, type_leaves " +
"where leaves.type_leave = type_leaves.id and " +
"leaves.type_application = type_applications.id";
ResultSet rs = stmt.executeQuery(sql);
DBTablePrinter.printResultSet(rs);
这将打印如下内容:
Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID | NAME | ID | NAME |
+----+------------------------+----+--------------------+----+--------------+
| 1 | green | 1 | application type 1 | 1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+
可以看出,name
列都在那里。 (我使用了我编写的 DBTablePrinter 实用程序类。如果您有兴趣,可以找到它 here)。正如 Strawberry 在评论中所做的那样,我还建议考虑使用显式连接语法。
我正在使用其他数据库 (H2),所以我不确定这是否适用于 MySQL,但您可以尝试(它对我有用):
// After executing the query
rs.next();
System.out.println(rs.getString("TYPE_LEAVES.NAME"));
System.out.println(rs.getString("TYPE_APPLICATIONS.NAME"));
// Prints:
// leave type 1
// application type 1
如果这不起作用,或者您确实需要为列名添加前缀并使用这些新名称访问它们,我能想到的就是这样的:
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);
// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
if (rsmd.getColumnLabel(i).equals("NAME")) {
if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
columns.put("L_NAME", new ArrayList<>());
} else {
columns.put("APP_NAME", new ArrayList<>());
}
} else {
columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
}
}
// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
String columnName = rsmd.getColumnLabel(i);
String tableName = rsmd.getTableName(i);
if (columnName.equals("NAME")) {
if (tableName.equals("TYPE_LEAVES")) {
columns.get("L_NAME").add(rs.getString(i));
} else {
columns.get("APP_NAME").add(rs.getString(i));
}
} else {
columns.get(columnName).add(rs.getString(i))
}
}
}
// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));
// Prints:
// leave type 1
// application type 1
关于java - 使用 MySQL 从 Java 中的多个表中选择带前缀的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26401197/