使用MySQL从Java中的多个表中选择带前缀的列

使用MySQL从Java中的多个表中选择带前缀的列,java,mysql,sql,prepared-statement,executequery,Java,Mysql,Sql,Prepared Statement,Executequery,我必须处理Java来创建一个restful API,我将它与MySQL一起使用来查询数据库 我对Java非常陌生,这可能是一个非常基本的问题,但我习惯于PHP框架,在这些框架中不存在这个问题,我想知道用Java做这件事的方法是什么 我查询了3个通过外键连接它们的表,发现如果其中两个表具有相同的列名,则只返回其中一个。在from语句中声明的最新表中的一个。看来他们被推翻了 例如,如果表type\u应用程序和type\u叶子都有名称列,则此查询中将仅返回type\u叶子中的名称列: select *

我必须处理Java来创建一个restful API,我将它与MySQL一起使用来查询数据库

我对Java非常陌生,这可能是一个非常基本的问题,但我习惯于PHP框架,在这些框架中不存在这个问题,我想知道用Java做这件事的方法是什么

我查询了3个通过外键连接它们的表,发现如果其中两个表具有相同的列名,则只返回其中一个。在
from
语句中声明的最新表中的一个。看来他们被推翻了

例如,如果表
type\u应用程序
type\u叶子
都有
名称
列,则此查询中将仅返回
type\u叶子
中的
名称
列:

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中如何处理它?

由于性能原因,“选择*”在大多数严重情况下都是一种不好的做法,我认为即使在PHP中也是一样的。

而且,即使使用“select*”也能正确返回该列,您可以使用result.getMetaData()来检查它

for (int i=1; i<rs.getMetaData().getColumnCount(); i++) {
    System.out.println(rs.getMetaData().getColumnName(i));
}
for(int i=1;i“select*”在大多数严重的情况下确实是一种不好的做法,因为性能问题,我认为即使在PHP中也是如此。

而且,即使使用“select*”也能正确返回该列,您可以使用result.getMetaData()来检查它

for (int i=1; i<rs.getMetaData().getColumnCount(); i++) {
    System.out.println(rs.getMetaData().getColumnName(i));
}

for(inti=1;i在这种情况下,可能会重命名其中一列

要解决此问题,可以从executeQuery(ResultSet.getMetaData方法)返回的结果集中查询列列表。这将返回

  • getColumnCount()将返回结果中的列数
  • getColumnLabel(int列)将返回该列的名称

  • 如果两列具有相同的名称“name”,则这两列的标签可能不同。

    在这种情况下,可能会重命名其中一列

    要解决此问题,可以从executeQuery(ResultSet.getMetaData方法)返回的结果集中查询列列表。这将返回

  • getColumnCount()将返回结果中的列数
  • getColumnLabel(int列)将返回该列的名称

  • 如果两列具有相同的名称“name”,则这两列的标签可能不同。

    您可以编写一个函数,根据表名和列名返回列的索引

    public int getIndex(ResultSet rs, String table, String column) throws SQLException
    {
        for (int i=1; i < rs.getMetaData().getColumnCount(); i++)
        {
            if (rs.getMetaData().getTableName(i).equals(table) && rs.getMetaData().getColumnName(i).equals(column))
            {
                return i;
            }
        }
        return -1;
    }
    

    您可以编写一个函数,根据表名和列名返回列的索引

    public int getIndex(ResultSet rs, String table, String column) throws SQLException
    {
        for (int i=1; i < rs.getMetaData().getColumnCount(); i++)
        {
            if (rs.getMetaData().getTableName(i).equals(table) && rs.getMetaData().getColumnName(i).equals(column))
            {
                return i;
            }
        }
        return -1;
    }
    

    我也是Java新手,所以我听到了;).但在我尽力回答您之前,如果您不介意的话,我想说一句话。您的问题与Java和数据库/SQL有关。您提供了一些SQL,其中解释了有关DB表的一些内容以及您可能从查询中获得的内容。但您的主要问题是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 |
    +----+------------------------+----+--------------------+----+--------------+
    
    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
    

    可以看到,两个代码>名称< /COD>列都在那里。(我使用了DabTable打印机实用程序类,我写了。如果您感兴趣的话,您可以找到它。我也建议,正如Strawberry在评论中所做的那样,考虑使用显式连接语法。

    我正在使用另一个DB(H2),因此我不确定这是否适用于MySQL,但您可以尝试(它适用于我):

    如果这不起作用,或者您真的需要在列名前加前缀,并使用这些新名称访问列名,那么我所能想到的就是这样:

    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 |
    +----+------------------------+----+--------------------+----+--------------+
    
    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
    
    ResultSetMetaData rsmd=rs.getMetaData();
    int columnCount=rsmd.getColumnCount();
    //以列名作为键的哈希映射
    Map columns=新的HashMap(columnCount);
    //循环浏览列,根据需要重命名
    
    对于(inti=1;i我也是Java新手,所以我听到了;).但在我尽力回答您之前,如果您不介意的话,我想说一句话。您的问题与Java和数据库/SQL有关。您提供了一些SQL,其中解释了有关DB表的一些内容以及您可能从查询中获得的内容。但您的主要问题是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 |
    +----+------------------------+----+--------------------+----+--------------+
    
    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
    

    可以看到,两个代码>名称< /COD>列都在那里。(我使用了DabTable打印机实用程序类,我写了。如果您感兴趣的话,您可以找到它。我也建议,正如Strawberry在评论中所做的那样,考虑使用显式连接语法。

    我正在使用另一个DB(H2),因此我不确定这是否适用于MySQL,但您可以尝试(它适用于我):

    如果这不起作用,或者您真的需要在列名前加前缀,并使用这些新名称访问列名,那么我所能想到的就是这样:

    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 |
    +----+------------------------+----+--------------------+----+--------------+
    
    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
    
    结果