I made an CRUD application in Java with JavaFX, H2 Embedded Database and Maven. Can you review my code quickly? Is it well written? What should I improve on it? I don't know if my code is written correctly, I'm a beginner in Java programming and I'm looking for advices. Where should I look for reviews of my code?
For more information, see the github repository
Here is my code:
public class Main extends Application {
@Override
public void start(Stage stage) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/view/MainView.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1080, 720);
scene.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/style.css")).toExternalForm());
Image icon = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/icon.png")));
stage.getIcons().add(icon);
stage.setTitle("Finance Manager");
stage.setResizable(false);
stage.setScene(scene);
stage.show();
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch();
}
}
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class Data {
private final int id;
private final String name;
private final String category;
private final float price;
private final String date;
}
public class MainController implements Initializable {
@FXML
private TextField total;
@FXML
private TextField search;
@FXML
private TextField errorField;
@FXML
private TextField nameField;
@FXML
private MenuButton categoryField;
@FXML
private TextField priceField;
@FXML
private DatePicker dateField;
@FXML
private TableView<Data> table;
@FXML
private TableColumn<Data, String> nameColumn;
@FXML
private TableColumn<Data, String> categoryColumn;
@FXML
private TableColumn<Data, Float> priceColumn;
@FXML
private TableColumn<Data, Date> dateColumn;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
showData();
dateField.setValue(LocalDate.now());
}
@FXML
private void addBtn() {
try {
if(categoryField.getText().equals("Select a category")) {
throw new NumberFormatException();
}
String query =
"INSERT INTO DATA VALUES (default,'" + nameField.getText() + "','" + categoryField.getText() +
"'," + Float.parseFloat(priceField.getText()) + ",'" + dateField.getValue().toString() +
"')";
executeUpdate(query);
showData();
errorField.clear();
}
catch(NumberFormatException e) {
errorField.setText("INCORRECT DATA");
}
}
@FXML
private void deleteBtn() {
Data data = table.getSelectionModel().getSelectedItem();
int id = data.getId();
String query =
"DELETE FROM DATA WHERE ID="+id+";";
executeUpdate(query);
showData();
}
@FXML
private void updateBtn() {
try {
if(categoryField.getText().equals("Select a category") || priceField.getText().startsWith("0")) {
throw new NumberFormatException();
}
Data data = table.getSelectionModel().getSelectedItem();
int id = data.getId();
String query =
"UPDATE DATA SET NAME ='" + nameField.getText() + "', CATEGORY = '" + categoryField.getText() + "'," + " PRICE = " +
Float.parseFloat(priceField.getText()) + ", DATE = '" + dateField.getValue().toString() + "' " +
"WHERE id = " + id + "";
executeUpdate(query);
showData();
errorField.clear();
}
catch(NumberFormatException e) {
errorField.setText("INCORRECT DATA");
}
}
@FXML
private void onMouseClickedTable() {
try {
Data data = table.getSelectionModel().getSelectedItem();
nameField.setText(data.getName());
categoryField.setText(data.getCategory());
priceField.setText(String.valueOf(data.getPrice()));
dateField.setValue(LocalDate.parse(data.getDate()));
}
catch (NullPointerException ignored) {
}
}
@FXML
private void category(ActionEvent event) {
String category = ((MenuItem) event.getSource()).getText();
switch (category) {
case "food" -> categoryField.setText("food");
case "cosmetics" -> categoryField.setText("cosmetics");
case "medicines" -> categoryField.setText("medicines");
case "bills" -> categoryField.setText("bills");
case "other" -> categoryField.setText("other");
}
}
private ObservableList<Data> getDataList() {
ObservableList<Data> dataList = FXCollections.observableArrayList();
DBConnection DBConnection = new DBConnection();
Connection connection = DBConnection.getConnection();
try {
PreparedStatement statement = connection.prepareStatement("SELECT * FROM DATA");
ResultSet result = statement.executeQuery();
while (result.next()) {
dataList.add(new Data(
result.getInt("id"),
result.getString("name"),
result.getString("category"),
result.getFloat("price"),
result.getString("date"))
);
}
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
return dataList;
}
private void showData() {
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
categoryColumn.setCellValueFactory(new PropertyValueFactory<>("category"));
priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
priceColumn.setCellFactory(price -> new TableCell<>() {
@Override
protected void updateItem(Float aFloat, boolean b) {
super.updateItem(aFloat, b);
if (aFloat == null || b) {
setText(null);
} else {
setText(String.format("%.2f", aFloat));
}
}
});
dateColumn.setCellValueFactory(new PropertyValueFactory<>("date"));
searchData();
dateColumn.setSortType(TableColumn.SortType.DESCENDING);
table.getSortOrder().add(dateColumn);
table.sort();
}
private void executeUpdate(String query) {
try {
DBConnection DBConnection = new DBConnection();
Connection connection = DBConnection.getConnection();
PreparedStatement statement = connection.prepareStatement(query);
statement.executeUpdate();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void searchData() {
FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
search.textProperty().addListener((observableValue, oldValue, newValue) -> filteredData.setPredicate(Data -> {
if(newValue.isEmpty() || newValue.isBlank()) {
return true;
}
String lowerCase = newValue.toLowerCase();
if(Data.getName().toLowerCase().contains(lowerCase)) {
return true;
}
else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
return true;
}
else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
return true;
}
else return String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase);
}));
SortedList<Data> sortedData = new SortedList<>(filteredData);
sortedData.comparatorProperty().bind(table.comparatorProperty());
table.setItems(sortedData);
sortedData.addListener((ListChangeListener.Change<? extends Data> c) -> setTotal());
setTotal();
}
private void setTotal() {
float totalAmount = 0;
totalAmount = table.getItems().stream().map(
Data::getPrice).reduce(totalAmount, Float::sum);
total.setText("Total: "+String.format("%.2f", totalAmount));
}
}
public class DBConnection {
String url = "jdbc:h2:./src/main/resources/db/data";
String username = "sa";
String password = "123";
public Connection getConnection() {
try {
return DriverManager.getConnection(url, username, password);
}
catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}