Я понимаю, что это очень старое сообщение и уже есть отличные ответы, но я хотел сделать простой MCVE, чтобы продемонстрировать один такой подход и позволить новым кодеру быстро увидеть концепцию в действии.
blockquote>В этом примере мы будем использовать 5 файлов:
- Main.java - просто используется для запуска приложения и вызова первого контроллера.
- Controller1.java - контроллер для первого макета FXML.
- Controller2.java - контроллер для второго макета FXML.
- Layout1.fxml - макет FXML для первого сцена.
- Layout2.fxml - макет FXML для второй сцены.
Все файлы перечислены полностью в нижней части этого сообщения.
Цель: показать переданные значения от
Controller1
доController2
и наоборот.Поток программы:
- Первая сцена содержит
TextField
,Button
иLabel
. Когда щелчокButton
щелкнут, второе окно загружается и отображается, включая текст, введенный вTextField
.- Внутри второй сцены есть также
TextField
,Button
, иLabel
.Label
отобразит текст, введенный вTextField
на первой сцене.- При вводе текста во второй сцене
TextField
и нажатииButton
первая сценаLabel
сцены обновлен, чтобы показать введенный текст.Это очень простая демонстрация и, безусловно, может означать некоторое улучшение, но должна сделать концепцию очень понятной.
Сам код также комментируется некоторые детали того, что происходит и как.
КОД
blockquote>Main.java:
import javafx.application.Application; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { // Create the first controller, which loads Layout1.fxml within its own constructor Controller1 controller1 = new Controller1(); // Show the new stage controller1.showStage(); } }
Controller1.java:
import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.stage.Stage; import java.io.IOException; public class Controller1 { // Holds this controller's Stage private final Stage thisStage; // Define the nodes from the Layout1.fxml file. This allows them to be referenced within the controller @FXML private TextField txtToSecondController; @FXML private Button btnOpenLayout2; @FXML private Label lblFromController2; public Controller1() { // Create the new stage thisStage = new Stage(); // Load the FXML file try { FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout1.fxml")); // Set this class as the controller loader.setController(this); // Load the scene thisStage.setScene(new Scene(loader.load())); // Setup the window/stage thisStage.setTitle("Passing Controllers Example - Layout1"); } catch (IOException e) { e.printStackTrace(); } } /** * Show the stage that was loaded in the constructor */ public void showStage() { thisStage.showAndWait(); } /** * The initialize() method allows you set setup your scene, adding actions, configuring nodes, etc. */ @FXML private void initialize() { // Add an action for the "Open Layout2" button btnOpenLayout2.setOnAction(event -> openLayout2()); } /** * Performs the action of loading and showing Layout2 */ private void openLayout2() { // Create the second controller, which loads its own FXML file. We pass a reference to this controller // using the keyword [this]; that allows the second controller to access the methods contained in here. Controller2 controller2 = new Controller2(this); // Show the new stage/window controller2.showStage(); } /** * Returns the text entered into txtToSecondController. This allows other controllers/classes to view that data. */ public String getEnteredText() { return txtToSecondController.getText(); } /** * Allows other controllers to set the text of this layout's Label */ public void setTextFromController2(String text) { lblFromController2.setText(text); } }
Controller2.java:
import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.stage.Stage; import java.io.IOException; public class Controller2 { // Holds this controller's Stage private Stage thisStage; // Will hold a reference to the first controller, allowing us to access the methods found there. private final Controller1 controller1; // Add references to the controls in Layout2.fxml @FXML private Label lblFromController1; @FXML private TextField txtToFirstController; @FXML private Button btnSetLayout1Text; public Controller2(Controller1 controller1) { // We received the first controller, now let's make it usable throughout this controller. this.controller1 = controller1; // Create the new stage thisStage = new Stage(); // Load the FXML file try { FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout2.fxml")); // Set this class as the controller loader.setController(this); // Load the scene thisStage.setScene(new Scene(loader.load())); // Setup the window/stage thisStage.setTitle("Passing Controllers Example - Layout2"); } catch (IOException e) { e.printStackTrace(); } } /** * Show the stage that was loaded in the constructor */ public void showStage() { thisStage.showAndWait(); } @FXML private void initialize() { // Set the label to whatever the text entered on Layout1 is lblFromController1.setText(controller1.getEnteredText()); // Set the action for the button btnSetLayout1Text.setOnAction(event -> setTextOnLayout1()); } /** * Calls the "setTextFromController2()" method on the first controller to update its Label */ private void setTextOnLayout1() { controller1.setTextFromController2(txtToFirstController.getText()); } }
Layout1.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.VBox?> <AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1"> <VBox alignment="CENTER" spacing="10.0"> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> </padding> <Label style="-fx-font-weight: bold;" text="This is Layout1!"/> <HBox alignment="CENTER_LEFT" spacing="10.0"> <Label text="Enter Text:"/> <TextField fx:id="txtToSecondController"/> <Button fx:id="btnOpenLayout2" mnemonicParsing="false" text="Open Layout2"/> </HBox> <VBox alignment="CENTER"> <Label text="Text From Controller2:"/> <Label fx:id="lblFromController2" text="Nothing Yet!"/> </VBox> </VBox> </AnchorPane>
Layout2.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.VBox?> <AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1"> <VBox alignment="CENTER" spacing="10.0"> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> </padding> <Label style="-fx-font-weight: bold;" text="Welcome to Layout 2!"/> <VBox alignment="CENTER"> <Label text="Text From Controller1:"/> <Label fx:id="lblFromController1" text="Nothing Yet!"/> </VBox> <HBox alignment="CENTER_LEFT" spacing="10.0"> <Label text="Enter Text:"/> <TextField fx:id="txtToFirstController"/> <Button fx:id="btnSetLayout1Text" mnemonicParsing="false" text="Set Text on Layout1"/> </HBox> </VBox> </AnchorPane>
Я вижу две возможных ситуации здесь. Во-первых, Вы хотите знать, существует ли стандарт SQL для этого, которое можно использовать в целом независимо от базы данных. Нет, нет. Во-вторых, Вы хотите знать относительно определенного продукта DBMS. Тогда необходимо определить его. Но я предполагаю, что наиболее вероятный ответ - то, что Вы возвратите что-то как "a.id, b.id", так как это - то, как необходимо было бы определить столбцы в SQL-выражении. И самый легкий способ узнать, каково значение по умолчанию, состоит в том, чтобы только отправить такой запрос и видеть то, что Вы возвращаете. Если Вы хотите определить, какой префикс прибывает перед точкой можно использовать "ВЫБОР * ОТ AS my_alias", например.
выберите *, обычно делает для плохого кода, поскольку новые столбцы имеют тенденцию быть добавленными или порядок изменения столбцов в таблицах вполне часто, которое обычно повреждает выбор * в очень тонкие пути. Так список столбцы является правильным решением.
относительно того, как сделать Ваш запрос, не уверенный в mysql, но в sqlserver, Вы могли выбрать имена столбцов из syscolumns и динамично создать избранный пункт.
Существует два способа, которыми я могу думать, чтобы заставить это произойти допускающим повторное использование способом. Нужно переименовать все Ваши столбцы с префиксом для таблицы, из которой они произошли. Я много раз видел это, но мне действительно не нравится он. Я нахожу, что это избыточно, причины большой ввод, и можно всегда использовать псевдонимы, когда необходимо покрыть случай возникающего имени столбца.
другой путь, который я рекомендовал бы Вам, делает в Вашей ситуации, если Вы стремитесь переживать это, должен создать представления для каждой таблицы, которые искажают имена таблиц. Тогда Вы присоединяетесь против тех представлений, а не таблиц. Тем путем Вы свободны использовать *, при необходимости свободный использовать исходные таблицы с именами первоначального столбца, при необходимости и это также делает запись любых последующих запросов легче, потому что Вы уже сделали работу переименования в представлениях.
Наконец, я не ясен, почему необходимо знать, из которого прибыла таблица каждый из столбцов. Это имеет значение? В конечном счете то, что имеет значение, является данными, которые они содержат. Произошел ли UserID из таблицы User, или таблица UserQuestion действительно не имеет значения. Имеет значение, конечно, когда необходимо обновить его, но в той точке необходимо уже знать, что схема достаточно хорошо определяет это.
Нет никакого стандарта SQL для этого.
Однако С генерацией кода (или по требованию поскольку таблицы составлены или изменены или во времени выполнения), можно сделать это довольно легко:
CREATE TABLE [dbo].[stackoverflow_329931_a](
[id] [int] IDENTITY(1,1) NOT NULL,
[col2] [nchar](10) NULL,
[col3] [nchar](10) NULL,
[col4] [nchar](10) NULL,
CONSTRAINT [PK_stackoverflow_329931_a] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[stackoverflow_329931_b](
[id] [int] IDENTITY(1,1) NOT NULL,
[col2] [nchar](10) NULL,
[col3] [nchar](10) NULL,
[col4] [nchar](10) NULL,
CONSTRAINT [PK_stackoverflow_329931_b] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
DECLARE @table1_name AS varchar(255)
DECLARE @table1_prefix AS varchar(255)
DECLARE @table2_name AS varchar(255)
DECLARE @table2_prefix AS varchar(255)
DECLARE @join_condition AS varchar(255)
SET @table1_name = 'stackoverflow_329931_a'
SET @table1_prefix = 'a_'
SET @table2_name = 'stackoverflow_329931_b'
SET @table2_prefix = 'b_'
SET @join_condition = 'a.[id] = b.[id]'
DECLARE @CRLF AS varchar(2)
SET @CRLF = CHAR(13) + CHAR(10)
DECLARE @a_columnlist AS varchar(MAX)
DECLARE @b_columnlist AS varchar(MAX)
DECLARE @sql AS varchar(MAX)
SELECT @a_columnlist = COALESCE(@a_columnlist + @CRLF + ',', '') + 'a.[' + COLUMN_NAME + '] AS [' + @table1_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table1_name
ORDER BY ORDINAL_POSITION
SELECT @b_columnlist = COALESCE(@b_columnlist + @CRLF + ',', '') + 'b.[' + COLUMN_NAME + '] AS [' + @table2_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table2_name
ORDER BY ORDINAL_POSITION
SET @sql = 'SELECT ' + @a_columnlist + '
,' + @b_columnlist + '
FROM [' + @table1_name + '] AS a
INNER JOIN [' + @table2_name + '] AS b
ON (' + @join_condition + ')'
PRINT @sql
-- EXEC (@sql)
Различные продукты базы данных дадут Вам различные ответы; но Вы собираетесь для вреда при переносе этого очень далеко. Вы - далеко более обеспеченный выбор столбцов, которые Вы хотите, и предоставление им Ваши собственные псевдонимы, таким образом, идентификационные данные каждого столбца совершенно ясны, и можно сказать им независимо в результатах.
Я натурален из той же лодки как OP - у меня есть десятки полей от 3 различных таблиц, к которым я присоединяюсь, некоторые из которых имеют то же имя (т.е. идентификатор, имя, и т.д.). Я не хочу перечислять каждое поле, таким образом, мое решение состояло в том, чтобы исказить те поля, которые совместно использовали имя, и используйте выбор * для тех, которые имеют уникальное имя.
, Например:
таблица a: идентификатор, имя, field1, field2...
таблица b: идентификатор, имя, field3, field4...
выбор a.id как ПОМОЩЬ, a.name как aName, a. *, b.id столь же предложенный, b.name как bName, b. *.....
При доступе к результатам I нас искаженные названия этих полей и игнорируют "исходные" имена.
, Возможно, не лучшее решение, но это работает на меня...., я - mysql
использования Единственная база данных я знаю это, делает это - SQLite, в зависимости от настроек, которые Вы настраиваете с PRAGMA full_column_names
и PRAGMA short_column_names
. См. http://www.sqlite.org/pragma.html
Иначе все, что я могу рекомендовать, должен выбрать столбцы в наборе результатов порядковым положением, а не именем столбца, если это - слишком много проблемы Вам для введения имен столбцов в запросе.
Это - хороший пример того, почему это - плохая практика для использования SELECT *
- потому что в конечном счете у Вас будет потребность вывести все имена столбцов так или иначе.
я понимаю потребность поддерживать столбцы, которые могут изменить имя или положение, но подстановочные знаки использования делают это тяжелее , не легче.
Или Вы могли использовать Красный SQL Логического элемента, Осуществляют рефакторинг или Подсказка SQL, которая разворачивает Ваш ВЫБОР * в списки столбцов щелчком кнопки
Tab так в Вашем случае, если Вы вводите в ВЫБОРЕ * ОТ СОЕДИНЕНИЯ B... Пойдите до конца *, кнопка Tab, вуаля! Вы будете видеть ВЫБОР Column1, Column2...., B.column1, B.column2 ОТ B
СОЕДИНЕНИЯ, Это не свободно хотя
Есть прямой ответ на ваш вопрос для тех, кто использует MySQL C-API.
Учитывая SQL:
SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y)
Результаты mysql_stmt_result_metadata () дают определение ваших полей из вашего подготовленного SQL-запроса в структуру MYSQL_FIELD []. Каждое поле содержит следующие данные:
char *name; /* Name of column (may be the alias) */
char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum enum_field_types type; /* Type of field. See mysql_com.h for types */
Обратите внимание на поля: catalog, table, org_name
Теперь вы знаете, какие поля в вашем SQL принадлежат какой схеме (также известной как каталог) и таблице. Этого достаточно для общей идентификации каждого поля из многотабличного sql-запроса без необходимости использования псевдонима.
Реальный продукт SqlYOG использует эти точные данные в такой усадьбе, что они могут независимо обновлять каждую таблицу соединения нескольких таблиц, когда присутствуют поля PK.
Если вас беспокоит изменение схемы, это может сработать для вас: 1. Выполните запрос «DESCRIBE table» для всех задействованных таблиц. 2. Используйте возвращенные имена полей для динамического создания строки имен столбцов с префиксом выбранного псевдонима.