Я пишу программу, использующую JavaFX, чтобы сделать простой способ отправки произвольных операторов SQL в произвольные базы данных.Думайте об этом как о версии ScriptRunner с графическим интерфейсом.Запросы выполняются в фоновом потоке.
Я не знаю количество и тип столбцов, которые мне понадобятся во время компиляции.На самом деле, я не буду знать, что будет в ResultSet, пока не получу ResultSet обратно из базы данных.В этот момент я хочу обработать данные соответствующим образом для их типа данных JDBC.Например, я назначаю Comparator каждому столбцу, чтобы пользователи могли сортировать отображаемые данные по любому столбцу, и он будет вести себя должным образом.
Я нашел критический код в StackOverflow (хотя с тех пор я потерял ссылку наэтот пост).Я ОЧЕНЬ благодарен за этот пост.Код работает, но он не совсем удовлетворителен, прежде всего потому, что он использует «необработанные типы» и снимает флажок приведения.С тех пор я сделал несколько изменений, пытаясь улучшить их, но, возможно, это привело к обратным результатам.Я был бы очень признателен, если бы кто-нибудь помог мне распутать это.Конечно, есть более элегантный способ.Если это так хорошо, как получится, это тоже будет хорошей информацией.
Кстати, весь мой проект в файлах .java: я не использую FXML или .css.
main () в этом примере кода просто вызывает код в processRequest ().
В основном я хочу узнать, как лучше всего объявлять и манипулировать переменными: «data», «columns» и «tvResult»,И если есть какие-то особые соображения.tvResult: что должно отображаться в графическом интерфейсе.данные: данные, которые возвращаются в ResultSet (dah).
столбцы: метаданные о столбцах, которые получены из ResultSetMetaData.
То, что у меня есть:
ObservableList<ObservableList<?>> data = FXCollections.observableArrayList();
ArrayList<TableColumn<?,?>> columns = new ArrayList<>();
private TableView<ObservableList<?>> tvResult;
код - это то, что я собрал из различных учебных пособий, ответов StackOverflow, книг, блогов и т. д. (обратите внимание на «vogella.com» в данных).
Данные, которые находятся в таблице:
SQL: «выбрать * из example.comments».
Вывод: 1 ||Ларс ||myemail@gmail.com ||http: \ www.vogella.com ||2009-09-14 ||Резюме ||Мой первый комментарий ||2 ||Стивен ||youremail@gmail.com ||http: \ www.google.com ||2018-11-20 ||Ваше резюме идет здесь ||Ваш первый комментарий ||
Извинение Извините, что здесь так много кода, я сократил его настолько, насколько мог, и все еще имею работающую программу для демонстрации вопроса.Я лишился работы в отдельном потоке, графического интерфейса и других тонкостей, чтобы мы могли сосредоточиться на коде, который меня интересует.
Это все еще немного дольше, чем это строго необходимо, но это потому, что я хотелсделать как можно меньше изменений в processRequest ().Он получает SQL в объекте String и Connection и манипулирует тремя упомянутыми переменными.
public class MySQLAccess extends Application {
ObservableList<ObservableList<?>> data = FXCollections.observableArrayList();
ArrayList<TableColumn<?,?>> columns = new ArrayList<>();
private TableView<ObservableList<?>> tvResult;
static MySQLAccess pgm;
/* ********************************************************************** **
** main()
** ********************************************************************** */
public static void main(String[] args) {
pgm = new MySQLAccess();
pgm.tvResult = new TableView<>();
Connection connection = null;
MysqlDataSource mySqlDataSource = new MysqlDataSource();
mySqlDataSource.setUrl("jdbc:mysql://" + "localhost" + ":3306/" + "StackOverflow");
mySqlDataSource.setUser("root");
mySqlDataSource.setPassword("");
DataSource dataSource = mySqlDataSource;
try {
connection = dataSource.getConnection();
pgm.processRequest("select * from example.comments", connection);
} catch (Exception e) {
System.out.println("error creating connection");
}
pgm.tvResult.getColumns().clear();
for (int j = 0; j < pgm.columns.size(); j++) {
TableColumn<?, ?> col = pgm.columns.get(j);
pgm.tvResult.getColumns().add((TableColumn<ObservableList<?>, ?>) col);
}
pgm.tvResult.setItems(pgm.data);
ObservableList<TableColumn<ObservableList<?>,?>> columns = pgm.tvResult.getColumns();
for (Object row : pgm.tvResult.getItems()) {
for (TableColumn column : columns) {
System.out.print(column.getCellObservableValue(row).getValue().toString() + " || ");
}
System.out.println();
}
}
/* ********************************************************************** **
** processRequest()
** ********************************************************************** */
private void processRequest(String sql, Connection connection) throws SQLException {
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(sql);
ResultSetMetaData rm = rs.getMetaData();
// Process Columns (assign the proper type to each)
int colCnt = rm.getColumnCount();
pgm.columns.clear();
for (int i = 0; i < colCnt; i++) {
final int k = i;
String columnName = rm.getColumnName(i + 1);
int columnType = rm.getColumnType(i + 1);
TableColumn col = new TableColumn(columnName);
col.setComparator(getComparator(columnType));
col.setCellValueFactory(
new Callback<CellDataFeatures<ObservableList<?>, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(
CellDataFeatures<ObservableList<?>, String> param) {
return new SimpleStringProperty(
param.getValue().get(k).toString());
}
});
pgm.columns.add(col);
}
// Process Rows
pgm.data.clear();
while (rs.next()) {
ObservableList<String> row = FXCollections.observableArrayList();
row.clear();
for (int i = 0; i < colCnt; i++) {
String str;
String hold = rs.getString(i + 1);
if ((hold == null) || (hold.isEmpty())) {
str = "";
} else {
str = String.valueOf(rs.getString(i + 1));
}
row.add(str);
}
pgm.data.add(row);
}
}
/* ********************************************************************** **
** getComparator()
** ********************************************************************** */
private Comparator<?> getComparator(int columnType) {
Comparator<?> comparator = null;
String objectType = DataTypeMapping.javaClass(columnType);
if (objectType.equals("String")) {
comparator = ((str_1, str_2) -> {
String int_1 = (String) str_1;
String int_2 = (String) str_2;
return int_1.compareTo(int_2);
});
} else if (objectType.equals("Integer")) {
comparator = ((str_1, str_2) -> {
Integer int_1 = Integer.parseInt((String) str_1);
Integer int_2 = Integer.parseInt((String) str_2);
return int_1.compareTo(int_2);
});
} else if (objectType.equals("Date")) {
comparator = ((str_1, str_2) -> {
Long date_1 = Long.parseLong((String) str_1);
Long date_2 = Long.parseLong((String) str_2);
return date_1.compareTo(date_2);
});
//
// .
// .
// .
//
} else {
comparator = null;
}
return comparator;
}
/* ********************************************************************** **
** start()
** *********************************************************************** */
@Override
public void start(Stage arg0) throws Exception {
}
}