├── .classpath
├── .gitignore
├── .project
├── build.fxbuild
├── db.properties
└── src
├── application
├── Main.java
└── application.css
├── db
├── DB.java
├── DbException.java
└── DbIntegrityException.java
├── gui
├── About.fxml
├── DepartmentForm.fxml
├── DepartmentFormController.java
├── DepartmentList.fxml
├── DepartmentListController.java
├── MainView.fxml
├── MainViewController.java
├── SellerForm.fxml
├── SellerFormController.java
├── SellerList.fxml
├── SellerListController.java
├── listeners
│ └── DataChangeListener.java
└── util
│ ├── Alerts.java
│ ├── Constraints.java
│ └── Utils.java
└── model
├── dao
├── DaoFactory.java
├── DepartmentDao.java
├── SellerDao.java
└── impl
│ ├── DepartmentDaoJDBC.java
│ └── SellerDaoJDBC.java
├── entities
├── Department.java
└── Seller.java
├── exceptions
└── ValidationException.java
└── services
├── DepartmentService.java
└── SellerService.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # build folders
26 | bin/
27 | target/
28 | nbproject/private/
29 | build/
30 | nbbuild/
31 | dist/
32 | nbdist/
33 |
34 | # Eclipse
35 | .settings/
36 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | workshop-javafx-jdbc
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/db.properties:
--------------------------------------------------------------------------------
1 | user=developer
2 | password=1234567
3 | dburl=jdbc:mysql://localhost:3306/coursejdbc
4 | useSSL=false
5 |
--------------------------------------------------------------------------------
/src/application/Main.java:
--------------------------------------------------------------------------------
1 | package application;
2 |
3 | import java.io.IOException;
4 |
5 | import javafx.application.Application;
6 | import javafx.fxml.FXMLLoader;
7 | import javafx.scene.Scene;
8 | import javafx.scene.control.ScrollPane;
9 | import javafx.stage.Stage;
10 |
11 | public class Main extends Application {
12 |
13 | private static Scene mainScene;
14 |
15 | @Override
16 | public void start(Stage primaryStage) {
17 | try {
18 | FXMLLoader loader = new FXMLLoader(getClass().getResource("/gui/MainView.fxml"));
19 | ScrollPane scrollPane = loader.load();
20 |
21 | scrollPane.setFitToHeight(true);
22 | scrollPane.setFitToWidth(true);
23 |
24 | mainScene = new Scene(scrollPane);
25 | primaryStage.setScene(mainScene);
26 | primaryStage.setTitle("Sample JavaFX application");
27 | primaryStage.show();
28 | } catch (IOException e) {
29 | e.printStackTrace();
30 | }
31 | }
32 |
33 | public static Scene getMainScene() {
34 | return mainScene;
35 | }
36 |
37 | public static void main(String[] args) {
38 | launch(args);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/application/application.css:
--------------------------------------------------------------------------------
1 | /* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
--------------------------------------------------------------------------------
/src/db/DB.java:
--------------------------------------------------------------------------------
1 | package db;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.IOException;
5 | import java.sql.Connection;
6 | import java.sql.DriverManager;
7 | import java.sql.ResultSet;
8 | import java.sql.SQLException;
9 | import java.sql.Statement;
10 | import java.util.Properties;
11 |
12 | public class DB {
13 |
14 | private static Connection conn = null;
15 |
16 | public static Connection getConnection() {
17 | if (conn == null) {
18 | try {
19 | Properties props = loadProperties();
20 | String url = props.getProperty("dburl");
21 | conn = DriverManager.getConnection(url, props);
22 | }
23 | catch (SQLException e) {
24 | throw new DbException(e.getMessage());
25 | }
26 | }
27 | return conn;
28 | }
29 |
30 | public static void closeConnection() {
31 | if (conn != null) {
32 | try {
33 | conn.close();
34 | } catch (SQLException e) {
35 | throw new DbException(e.getMessage());
36 | }
37 | }
38 | }
39 |
40 | private static Properties loadProperties() {
41 | try (FileInputStream fs = new FileInputStream("db.properties")) {
42 | Properties props = new Properties();
43 | props.load(fs);
44 | return props;
45 | }
46 | catch (IOException e) {
47 | throw new DbException(e.getMessage());
48 | }
49 | }
50 |
51 | public static void closeStatement(Statement st) {
52 | if (st != null) {
53 | try {
54 | st.close();
55 | } catch (SQLException e) {
56 | throw new DbException(e.getMessage());
57 | }
58 | }
59 | }
60 |
61 | public static void closeResultSet(ResultSet rs) {
62 | if (rs != null) {
63 | try {
64 | rs.close();
65 | } catch (SQLException e) {
66 | throw new DbException(e.getMessage());
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/db/DbException.java:
--------------------------------------------------------------------------------
1 | package db;
2 |
3 | public class DbException extends RuntimeException {
4 | private static final long serialVersionUID = 1L;
5 |
6 | public DbException(String msg) {
7 | super(msg);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/db/DbIntegrityException.java:
--------------------------------------------------------------------------------
1 | package db;
2 |
3 | public class DbIntegrityException extends RuntimeException {
4 | private static final long serialVersionUID = 1L;
5 |
6 | public DbIntegrityException(String msg) {
7 | super(msg);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/gui/About.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/gui/DepartmentForm.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/gui/DepartmentFormController.java:
--------------------------------------------------------------------------------
1 | package gui;
2 |
3 | import java.net.URL;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.ResourceBundle;
8 | import java.util.Set;
9 |
10 | import db.DbException;
11 | import gui.listeners.DataChangeListener;
12 | import gui.util.Alerts;
13 | import gui.util.Constraints;
14 | import gui.util.Utils;
15 | import javafx.event.ActionEvent;
16 | import javafx.fxml.FXML;
17 | import javafx.fxml.Initializable;
18 | import javafx.scene.control.Alert.AlertType;
19 | import javafx.scene.control.Button;
20 | import javafx.scene.control.Label;
21 | import javafx.scene.control.TextField;
22 | import model.entities.Department;
23 | import model.exceptions.ValidationException;
24 | import model.services.DepartmentService;
25 |
26 | public class DepartmentFormController implements Initializable {
27 |
28 | private Department entity;
29 |
30 | private DepartmentService service;
31 |
32 | private List dataChangeListeners = new ArrayList<>();
33 |
34 | @FXML
35 | private TextField txtId;
36 |
37 | @FXML
38 | private TextField txtName;
39 |
40 | @FXML
41 | private Label labelErrorName;
42 |
43 | @FXML
44 | private Button btSave;
45 |
46 | @FXML
47 | private Button btCancel;
48 |
49 | public void setDepartment(Department entity) {
50 | this.entity = entity;
51 | }
52 |
53 | public void setDepartmentService(DepartmentService service) {
54 | this.service = service;
55 | }
56 |
57 | public void subscribeDataChangeListener(DataChangeListener listener) {
58 | dataChangeListeners.add(listener);
59 | }
60 |
61 | @FXML
62 | public void onBtSaveAction(ActionEvent event) {
63 | if (entity == null) {
64 | throw new IllegalStateException("Entity was null");
65 | }
66 | if (service == null) {
67 | throw new IllegalStateException("Service was null");
68 | }
69 | try {
70 | entity = getFormData();
71 | service.saveOrUpdate(entity);
72 | notifyDataChangeListeners();
73 | Utils.currentStage(event).close();
74 | }
75 | catch (ValidationException e) {
76 | setErrorMessages(e.getErrors());
77 | }
78 | catch (DbException e) {
79 | Alerts.showAlert("Error saving object", null, e.getMessage(), AlertType.ERROR);
80 | }
81 | }
82 |
83 | private void notifyDataChangeListeners() {
84 | for (DataChangeListener listener : dataChangeListeners) {
85 | listener.onDataChanged();
86 | }
87 | }
88 |
89 | private Department getFormData() {
90 | Department obj = new Department();
91 |
92 | ValidationException exception = new ValidationException("Validation error");
93 |
94 | obj.setId(Utils.tryParseToInt(txtId.getText()));
95 |
96 | if (txtName.getText() == null || txtName.getText().trim().equals("")) {
97 | exception.addError("name", "Field can't be empty");
98 | }
99 | obj.setName(txtName.getText());
100 |
101 | if (exception.getErrors().size() > 0) {
102 | throw exception;
103 | }
104 |
105 | return obj;
106 | }
107 |
108 | @FXML
109 | public void onBtCancelAction(ActionEvent event) {
110 | Utils.currentStage(event).close();
111 | }
112 |
113 | @Override
114 | public void initialize(URL url, ResourceBundle rb) {
115 | initializeNodes();
116 | }
117 |
118 | private void initializeNodes() {
119 | Constraints.setTextFieldInteger(txtId);
120 | Constraints.setTextFieldMaxLength(txtName, 30);
121 | }
122 |
123 | public void updateFormData() {
124 | if (entity == null) {
125 | throw new IllegalStateException("Entity was null");
126 | }
127 | txtId.setText(String.valueOf(entity.getId()));
128 | txtName.setText(entity.getName());
129 | }
130 |
131 | private void setErrorMessages(Map errors) {
132 | Set fields = errors.keySet();
133 |
134 | if (fields.contains("name")) {
135 | labelErrorName.setText(errors.get("name"));
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/gui/DepartmentList.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/gui/DepartmentListController.java:
--------------------------------------------------------------------------------
1 | package gui;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 | import java.util.List;
6 | import java.util.Optional;
7 | import java.util.ResourceBundle;
8 |
9 | import application.Main;
10 | import db.DbIntegrityException;
11 | import gui.listeners.DataChangeListener;
12 | import gui.util.Alerts;
13 | import gui.util.Utils;
14 | import javafx.beans.property.ReadOnlyObjectWrapper;
15 | import javafx.collections.FXCollections;
16 | import javafx.collections.ObservableList;
17 | import javafx.event.ActionEvent;
18 | import javafx.fxml.FXML;
19 | import javafx.fxml.FXMLLoader;
20 | import javafx.fxml.Initializable;
21 | import javafx.scene.Scene;
22 | import javafx.scene.control.Alert.AlertType;
23 | import javafx.scene.control.Button;
24 | import javafx.scene.control.ButtonType;
25 | import javafx.scene.control.TableCell;
26 | import javafx.scene.control.TableColumn;
27 | import javafx.scene.control.TableView;
28 | import javafx.scene.control.cell.PropertyValueFactory;
29 | import javafx.scene.layout.Pane;
30 | import javafx.stage.Modality;
31 | import javafx.stage.Stage;
32 | import model.entities.Department;
33 | import model.services.DepartmentService;
34 |
35 | public class DepartmentListController implements Initializable, DataChangeListener {
36 |
37 | private DepartmentService service;
38 |
39 | @FXML
40 | private TableView tableViewDepartment;
41 |
42 | @FXML
43 | private TableColumn tableColumnId;
44 |
45 | @FXML
46 | private TableColumn tableColumnName;
47 |
48 | @FXML
49 | private TableColumn tableColumnEDIT;
50 |
51 | @FXML
52 | private TableColumn tableColumnREMOVE;
53 |
54 | @FXML
55 | private Button btNew;
56 |
57 | private ObservableList obsList;
58 |
59 | @FXML
60 | public void onBtNewAction(ActionEvent event) {
61 | Stage parentStage = Utils.currentStage(event);
62 | Department obj = new Department();
63 | createDialogForm(obj, "/gui/DepartmentForm.fxml", parentStage);
64 | }
65 |
66 | public void setDepartmentService(DepartmentService service) {
67 | this.service = service;
68 | }
69 |
70 | @Override
71 | public void initialize(URL url, ResourceBundle rb) {
72 | initializeNodes();
73 | }
74 |
75 | private void initializeNodes() {
76 | tableColumnId.setCellValueFactory(new PropertyValueFactory<>("id"));
77 | tableColumnName.setCellValueFactory(new PropertyValueFactory<>("name"));
78 |
79 | Stage stage = (Stage) Main.getMainScene().getWindow();
80 | tableViewDepartment.prefHeightProperty().bind(stage.heightProperty());
81 | }
82 |
83 | public void updateTableView() {
84 | if (service == null) {
85 | throw new IllegalStateException("Service was null");
86 | }
87 | List list = service.findAll();
88 | obsList = FXCollections.observableArrayList(list);
89 | tableViewDepartment.setItems(obsList);
90 | initEditButtons();
91 | initRemoveButtons();
92 | }
93 |
94 | private void createDialogForm(Department obj, String absoluteName, Stage parentStage) {
95 | try {
96 | FXMLLoader loader = new FXMLLoader(getClass().getResource(absoluteName));
97 | Pane pane = loader.load();
98 |
99 | DepartmentFormController controller = loader.getController();
100 | controller.setDepartment(obj);
101 | controller.setDepartmentService(new DepartmentService());
102 | controller.subscribeDataChangeListener(this);
103 | controller.updateFormData();
104 |
105 | Stage dialogStage = new Stage();
106 | dialogStage.setTitle("Enter Department data");
107 | dialogStage.setScene(new Scene(pane));
108 | dialogStage.setResizable(false);
109 | dialogStage.initOwner(parentStage);
110 | dialogStage.initModality(Modality.WINDOW_MODAL);
111 | dialogStage.showAndWait();
112 | } catch (IOException e) {
113 | e.printStackTrace();
114 | Alerts.showAlert("IO Exception", "Error loading view", e.getMessage(), AlertType.ERROR);
115 | }
116 | }
117 |
118 | @Override
119 | public void onDataChanged() {
120 | updateTableView();
121 | }
122 |
123 | private void initEditButtons() {
124 | tableColumnEDIT.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
125 | tableColumnEDIT.setCellFactory(param -> new TableCell() {
126 | private final Button button = new Button("edit");
127 |
128 | @Override
129 | protected void updateItem(Department obj, boolean empty) {
130 | super.updateItem(obj, empty);
131 | if (obj == null) {
132 | setGraphic(null);
133 | return;
134 | }
135 | setGraphic(button);
136 | button.setOnAction(
137 | event -> createDialogForm(obj, "/gui/DepartmentForm.fxml", Utils.currentStage(event)));
138 | }
139 | });
140 | }
141 |
142 | private void initRemoveButtons() {
143 | tableColumnREMOVE.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
144 | tableColumnREMOVE.setCellFactory(param -> new TableCell() {
145 | private final Button button = new Button("remove");
146 |
147 | @Override
148 | protected void updateItem(Department obj, boolean empty) {
149 | super.updateItem(obj, empty);
150 | if (obj == null) {
151 | setGraphic(null);
152 | return;
153 | }
154 | setGraphic(button);
155 | button.setOnAction(event -> removeEntity(obj));
156 | }
157 | });
158 | }
159 |
160 | private void removeEntity(Department obj) {
161 | Optional result = Alerts.showConfirmation("Confirmation", "Are you sure to delete?");
162 |
163 | if (result.get() == ButtonType.OK) {
164 | if (service == null) {
165 | throw new IllegalStateException("Service was null");
166 | }
167 | try {
168 | service.remove(obj);
169 | updateTableView();
170 | }
171 | catch (DbIntegrityException e) {
172 | Alerts.showAlert("Error removing object", null, e.getMessage(), AlertType.ERROR);
173 | }
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/gui/MainView.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/gui/MainViewController.java:
--------------------------------------------------------------------------------
1 | package gui;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 | import java.util.ResourceBundle;
6 | import java.util.function.Consumer;
7 |
8 | import application.Main;
9 | import gui.util.Alerts;
10 | import javafx.fxml.FXML;
11 | import javafx.fxml.FXMLLoader;
12 | import javafx.fxml.Initializable;
13 | import javafx.scene.Node;
14 | import javafx.scene.Scene;
15 | import javafx.scene.control.Alert.AlertType;
16 | import javafx.scene.control.MenuItem;
17 | import javafx.scene.control.ScrollPane;
18 | import javafx.scene.layout.VBox;
19 | import model.services.DepartmentService;
20 | import model.services.SellerService;
21 |
22 | public class MainViewController implements Initializable {
23 |
24 | @FXML
25 | private MenuItem menuItemSeller;
26 |
27 | @FXML
28 | private MenuItem menuItemDepartment;
29 |
30 | @FXML
31 | private MenuItem menuItemAbout;
32 |
33 | @FXML
34 | public void onMenuItemSellerAction() {
35 | loadView("/gui/SellerList.fxml", (SellerListController controller) -> {
36 | controller.setSellerService(new SellerService());
37 | controller.updateTableView();
38 | });
39 | }
40 |
41 | @FXML
42 | public void onMenuItemDepartmentAction() {
43 | loadView("/gui/DepartmentList.fxml", (DepartmentListController controller) -> {
44 | controller.setDepartmentService(new DepartmentService());
45 | controller.updateTableView();
46 | });
47 | }
48 |
49 | @FXML
50 | public void onMenuItemAboutAction() {
51 | loadView("/gui/About.fxml", x -> {});
52 | }
53 |
54 | @Override
55 | public void initialize(URL uri, ResourceBundle rb) {
56 | }
57 |
58 | private synchronized void loadView(String absoluteName, Consumer initializingAction) {
59 | try {
60 | FXMLLoader loader = new FXMLLoader(getClass().getResource(absoluteName));
61 | VBox newVBox = loader.load();
62 |
63 | Scene mainScene = Main.getMainScene();
64 | VBox mainVBox = (VBox) ((ScrollPane) mainScene.getRoot()).getContent();
65 |
66 | Node mainMenu = mainVBox.getChildren().get(0);
67 | mainVBox.getChildren().clear();
68 | mainVBox.getChildren().add(mainMenu);
69 | mainVBox.getChildren().addAll(newVBox.getChildren());
70 |
71 | T controller = loader.getController();
72 | initializingAction.accept(controller);
73 | }
74 | catch (IOException e) {
75 | Alerts.showAlert("IO Exception", "Error loading view", e.getMessage(), AlertType.ERROR);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/gui/SellerForm.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/gui/SellerFormController.java:
--------------------------------------------------------------------------------
1 | package gui;
2 |
3 | import java.net.URL;
4 | import java.time.Instant;
5 | import java.time.LocalDate;
6 | import java.time.ZoneId;
7 | import java.util.ArrayList;
8 | import java.util.Date;
9 | import java.util.List;
10 | import java.util.Locale;
11 | import java.util.Map;
12 | import java.util.ResourceBundle;
13 | import java.util.Set;
14 |
15 | import db.DbException;
16 | import gui.listeners.DataChangeListener;
17 | import gui.util.Alerts;
18 | import gui.util.Constraints;
19 | import gui.util.Utils;
20 | import javafx.collections.FXCollections;
21 | import javafx.collections.ObservableList;
22 | import javafx.event.ActionEvent;
23 | import javafx.fxml.FXML;
24 | import javafx.fxml.Initializable;
25 | import javafx.scene.control.Alert.AlertType;
26 | import javafx.scene.control.Button;
27 | import javafx.scene.control.ComboBox;
28 | import javafx.scene.control.DatePicker;
29 | import javafx.scene.control.Label;
30 | import javafx.scene.control.ListCell;
31 | import javafx.scene.control.ListView;
32 | import javafx.scene.control.TextField;
33 | import javafx.util.Callback;
34 | import model.entities.Department;
35 | import model.entities.Seller;
36 | import model.exceptions.ValidationException;
37 | import model.services.DepartmentService;
38 | import model.services.SellerService;
39 |
40 | public class SellerFormController implements Initializable {
41 |
42 | private Seller entity;
43 |
44 | private SellerService service;
45 |
46 | private DepartmentService departmentService;
47 |
48 | private List dataChangeListeners = new ArrayList<>();
49 |
50 | @FXML
51 | private TextField txtId;
52 |
53 | @FXML
54 | private TextField txtName;
55 |
56 | @FXML
57 | private TextField txtEmail;
58 |
59 | @FXML
60 | private DatePicker dpBirthDate;
61 |
62 | @FXML
63 | private TextField txtBaseSalary;
64 |
65 | @FXML
66 | private ComboBox comboBoxDepartment;
67 |
68 | @FXML
69 | private Label labelErrorName;
70 |
71 | @FXML
72 | private Label labelErrorEmail;
73 |
74 | @FXML
75 | private Label labelErrorBirthDate;
76 |
77 | @FXML
78 | private Label labelErrorBaseSalary;
79 |
80 | @FXML
81 | private Button btSave;
82 |
83 | @FXML
84 | private Button btCancel;
85 |
86 | private ObservableList obsList;
87 |
88 | public void setSeller(Seller entity) {
89 | this.entity = entity;
90 | }
91 |
92 | public void setServices(SellerService service, DepartmentService departmentService) {
93 | this.service = service;
94 | this.departmentService = departmentService;
95 | }
96 |
97 | public void subscribeDataChangeListener(DataChangeListener listener) {
98 | dataChangeListeners.add(listener);
99 | }
100 |
101 | @FXML
102 | public void onBtSaveAction(ActionEvent event) {
103 | if (entity == null) {
104 | throw new IllegalStateException("Entity was null");
105 | }
106 | if (service == null) {
107 | throw new IllegalStateException("Service was null");
108 | }
109 | try {
110 | entity = getFormData();
111 | service.saveOrUpdate(entity);
112 | notifyDataChangeListeners();
113 | Utils.currentStage(event).close();
114 | } catch (ValidationException e) {
115 | setErrorMessages(e.getErrors());
116 | } catch (DbException e) {
117 | Alerts.showAlert("Error saving object", null, e.getMessage(), AlertType.ERROR);
118 | }
119 | }
120 |
121 | private void notifyDataChangeListeners() {
122 | for (DataChangeListener listener : dataChangeListeners) {
123 | listener.onDataChanged();
124 | }
125 | }
126 |
127 | private Seller getFormData() {
128 | Seller obj = new Seller();
129 |
130 | ValidationException exception = new ValidationException("Validation error");
131 |
132 | obj.setId(Utils.tryParseToInt(txtId.getText()));
133 |
134 | if (txtName.getText() == null || txtName.getText().trim().equals("")) {
135 | exception.addError("name", "Field can't be empty");
136 | }
137 | obj.setName(txtName.getText());
138 |
139 | if (txtEmail.getText() == null || txtEmail.getText().trim().equals("")) {
140 | exception.addError("email", "Field can't be empty");
141 | }
142 | obj.setEmail(txtEmail.getText());
143 |
144 | if (dpBirthDate.getValue() == null) {
145 | exception.addError("birthDate", "Field can't be empty");
146 | }
147 | else {
148 | Instant instant = Instant.from(dpBirthDate.getValue().atStartOfDay(ZoneId.systemDefault()));
149 | obj.setBirthDate(Date.from(instant));
150 | }
151 |
152 | if (txtBaseSalary.getText() == null || txtBaseSalary.getText().trim().equals("")) {
153 | exception.addError("baseSalary", "Field can't be empty");
154 | }
155 | obj.setBaseSalary(Utils.tryParseToDouble(txtBaseSalary.getText()));
156 |
157 | obj.setDepartment(comboBoxDepartment.getValue());
158 |
159 | if (exception.getErrors().size() > 0) {
160 | throw exception;
161 | }
162 |
163 | return obj;
164 | }
165 |
166 | @FXML
167 | public void onBtCancelAction(ActionEvent event) {
168 | Utils.currentStage(event).close();
169 | }
170 |
171 | @Override
172 | public void initialize(URL url, ResourceBundle rb) {
173 | initializeNodes();
174 | }
175 |
176 | private void initializeNodes() {
177 | Constraints.setTextFieldInteger(txtId);
178 | Constraints.setTextFieldMaxLength(txtName, 70);
179 | Constraints.setTextFieldDouble(txtBaseSalary);
180 | Constraints.setTextFieldMaxLength(txtEmail, 60);
181 | Utils.formatDatePicker(dpBirthDate, "dd/MM/yyyy");
182 |
183 | initializeComboBoxDepartment();
184 | }
185 |
186 | public void updateFormData() {
187 | if (entity == null) {
188 | throw new IllegalStateException("Entity was null");
189 | }
190 | txtId.setText(String.valueOf(entity.getId()));
191 | txtName.setText(entity.getName());
192 | txtEmail.setText(entity.getEmail());
193 | Locale.setDefault(Locale.US);
194 | txtBaseSalary.setText(String.format("%.2f", entity.getBaseSalary()));
195 | if (entity.getBirthDate() != null) {
196 | dpBirthDate.setValue(LocalDate.ofInstant(entity.getBirthDate().toInstant(), ZoneId.systemDefault()));
197 | }
198 | if (entity.getDepartment() == null) {
199 | comboBoxDepartment.getSelectionModel().selectFirst();
200 | } else {
201 | comboBoxDepartment.setValue(entity.getDepartment());
202 | }
203 | }
204 |
205 | public void loadAssociatedObjects() {
206 | if (departmentService == null) {
207 | throw new IllegalStateException("DepartmentService was null");
208 | }
209 | List list = departmentService.findAll();
210 | obsList = FXCollections.observableArrayList(list);
211 | comboBoxDepartment.setItems(obsList);
212 | }
213 |
214 | private void setErrorMessages(Map errors) {
215 | Set fields = errors.keySet();
216 |
217 | labelErrorName.setText((fields.contains("name") ? errors.get("name") : ""));
218 | labelErrorEmail.setText((fields.contains("email") ? errors.get("email") : ""));
219 | labelErrorBirthDate.setText((fields.contains("birthDate") ? errors.get("birthDate") : ""));
220 | labelErrorBaseSalary.setText((fields.contains("baseSalary") ? errors.get("baseSalary") : ""));
221 | }
222 |
223 | private void initializeComboBoxDepartment() {
224 | Callback, ListCell> factory = lv -> new ListCell() {
225 | @Override
226 | protected void updateItem(Department item, boolean empty) {
227 | super.updateItem(item, empty);
228 | setText(empty ? "" : item.getName());
229 | }
230 | };
231 | comboBoxDepartment.setCellFactory(factory);
232 | comboBoxDepartment.setButtonCell(factory.call(null));
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/src/gui/SellerList.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/gui/SellerListController.java:
--------------------------------------------------------------------------------
1 | package gui;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 | import java.util.Date;
6 | import java.util.List;
7 | import java.util.Optional;
8 | import java.util.ResourceBundle;
9 |
10 | import application.Main;
11 | import db.DbIntegrityException;
12 | import gui.listeners.DataChangeListener;
13 | import gui.util.Alerts;
14 | import gui.util.Utils;
15 | import javafx.beans.property.ReadOnlyObjectWrapper;
16 | import javafx.collections.FXCollections;
17 | import javafx.collections.ObservableList;
18 | import javafx.event.ActionEvent;
19 | import javafx.fxml.FXML;
20 | import javafx.fxml.FXMLLoader;
21 | import javafx.fxml.Initializable;
22 | import javafx.scene.Scene;
23 | import javafx.scene.control.Alert.AlertType;
24 | import javafx.scene.control.Button;
25 | import javafx.scene.control.ButtonType;
26 | import javafx.scene.control.TableCell;
27 | import javafx.scene.control.TableColumn;
28 | import javafx.scene.control.TableView;
29 | import javafx.scene.control.cell.PropertyValueFactory;
30 | import javafx.scene.layout.Pane;
31 | import javafx.stage.Modality;
32 | import javafx.stage.Stage;
33 | import model.entities.Seller;
34 | import model.services.DepartmentService;
35 | import model.services.SellerService;
36 |
37 | public class SellerListController implements Initializable, DataChangeListener {
38 |
39 | private SellerService service;
40 |
41 | @FXML
42 | private TableView tableViewSeller;
43 |
44 | @FXML
45 | private TableColumn tableColumnId;
46 |
47 | @FXML
48 | private TableColumn tableColumnName;
49 |
50 | @FXML
51 | private TableColumn tableColumnEmail;
52 |
53 | @FXML
54 | private TableColumn tableColumnBirthDate;
55 |
56 | @FXML
57 | private TableColumn tableColumnBaseSalary;
58 |
59 | @FXML
60 | private TableColumn tableColumnEDIT;
61 |
62 | @FXML
63 | private TableColumn tableColumnREMOVE;
64 |
65 | @FXML
66 | private Button btNew;
67 |
68 | private ObservableList obsList;
69 |
70 | @FXML
71 | public void onBtNewAction(ActionEvent event) {
72 | Stage parentStage = Utils.currentStage(event);
73 | Seller obj = new Seller();
74 | createDialogForm(obj, "/gui/SellerForm.fxml", parentStage);
75 | }
76 |
77 | public void setSellerService(SellerService service) {
78 | this.service = service;
79 | }
80 |
81 | @Override
82 | public void initialize(URL url, ResourceBundle rb) {
83 | initializeNodes();
84 | }
85 |
86 | private void initializeNodes() {
87 | tableColumnId.setCellValueFactory(new PropertyValueFactory<>("id"));
88 | tableColumnName.setCellValueFactory(new PropertyValueFactory<>("name"));
89 | tableColumnEmail.setCellValueFactory(new PropertyValueFactory<>("email"));
90 | tableColumnBirthDate.setCellValueFactory(new PropertyValueFactory<>("birthDate"));
91 | Utils.formatTableColumnDate(tableColumnBirthDate, "dd/MM/yyyy");
92 | tableColumnBaseSalary.setCellValueFactory(new PropertyValueFactory<>("baseSalary"));
93 | Utils.formatTableColumnDouble(tableColumnBaseSalary, 2);
94 |
95 | Stage stage = (Stage) Main.getMainScene().getWindow();
96 | tableViewSeller.prefHeightProperty().bind(stage.heightProperty());
97 | }
98 |
99 | public void updateTableView() {
100 | if (service == null) {
101 | throw new IllegalStateException("Service was null");
102 | }
103 | List list = service.findAll();
104 | obsList = FXCollections.observableArrayList(list);
105 | tableViewSeller.setItems(obsList);
106 | initEditButtons();
107 | initRemoveButtons();
108 | }
109 |
110 | private void createDialogForm(Seller obj, String absoluteName, Stage parentStage) {
111 | try {
112 | FXMLLoader loader = new FXMLLoader(getClass().getResource(absoluteName));
113 | Pane pane = loader.load();
114 |
115 | SellerFormController controller = loader.getController();
116 | controller.setSeller(obj);
117 | controller.setServices(new SellerService(), new DepartmentService());
118 | controller.loadAssociatedObjects();
119 | controller.subscribeDataChangeListener(this);
120 | controller.updateFormData();
121 |
122 | Stage dialogStage = new Stage();
123 | dialogStage.setTitle("Enter Seller data");
124 | dialogStage.setScene(new Scene(pane));
125 | dialogStage.setResizable(false);
126 | dialogStage.initOwner(parentStage);
127 | dialogStage.initModality(Modality.WINDOW_MODAL);
128 | dialogStage.showAndWait();
129 | } catch (IOException e) {
130 | e.printStackTrace();
131 | Alerts.showAlert("IO Exception", "Error loading view", e.getMessage(), AlertType.ERROR);
132 | }
133 | }
134 |
135 | @Override
136 | public void onDataChanged() {
137 | updateTableView();
138 | }
139 |
140 | private void initEditButtons() {
141 | tableColumnEDIT.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
142 | tableColumnEDIT.setCellFactory(param -> new TableCell() {
143 | private final Button button = new Button("edit");
144 |
145 | @Override
146 | protected void updateItem(Seller obj, boolean empty) {
147 | super.updateItem(obj, empty);
148 | if (obj == null) {
149 | setGraphic(null);
150 | return;
151 | }
152 | setGraphic(button);
153 | button.setOnAction(
154 | event -> createDialogForm(obj, "/gui/SellerForm.fxml", Utils.currentStage(event)));
155 | }
156 | });
157 | }
158 |
159 | private void initRemoveButtons() {
160 | tableColumnREMOVE.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
161 | tableColumnREMOVE.setCellFactory(param -> new TableCell() {
162 | private final Button button = new Button("remove");
163 |
164 | @Override
165 | protected void updateItem(Seller obj, boolean empty) {
166 | super.updateItem(obj, empty);
167 | if (obj == null) {
168 | setGraphic(null);
169 | return;
170 | }
171 | setGraphic(button);
172 | button.setOnAction(event -> removeEntity(obj));
173 | }
174 | });
175 | }
176 |
177 | private void removeEntity(Seller obj) {
178 | Optional result = Alerts.showConfirmation("Confirmation", "Are you sure to delete?");
179 |
180 | if (result.get() == ButtonType.OK) {
181 | if (service == null) {
182 | throw new IllegalStateException("Service was null");
183 | }
184 | try {
185 | service.remove(obj);
186 | updateTableView();
187 | }
188 | catch (DbIntegrityException e) {
189 | Alerts.showAlert("Error removing object", null, e.getMessage(), AlertType.ERROR);
190 | }
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/src/gui/listeners/DataChangeListener.java:
--------------------------------------------------------------------------------
1 | package gui.listeners;
2 |
3 | public interface DataChangeListener {
4 |
5 | void onDataChanged();
6 | }
7 |
--------------------------------------------------------------------------------
/src/gui/util/Alerts.java:
--------------------------------------------------------------------------------
1 | package gui.util;
2 |
3 | import java.util.Optional;
4 |
5 | import javafx.scene.control.Alert;
6 | import javafx.scene.control.Alert.AlertType;
7 | import javafx.scene.control.ButtonType;
8 |
9 | public class Alerts {
10 |
11 | public static void showAlert(String title, String header, String content, AlertType type) {
12 | Alert alert = new Alert(type);
13 | alert.setTitle(title);
14 | alert.setHeaderText(header);
15 | alert.setContentText(content);
16 | alert.show();
17 | }
18 |
19 | public static Optional showConfirmation(String title, String content) {
20 | Alert alert = new Alert(AlertType.CONFIRMATION);
21 | alert.setTitle(title);
22 | alert.setHeaderText(null);
23 | alert.setContentText(content);
24 | return alert.showAndWait();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/gui/util/Constraints.java:
--------------------------------------------------------------------------------
1 | package gui.util;
2 |
3 | import javafx.scene.control.TextField;
4 |
5 | public class Constraints {
6 |
7 | public static void setTextFieldInteger(TextField txt) {
8 | txt.textProperty().addListener((obs, oldValue, newValue) -> {
9 | if (newValue != null && !newValue.matches("\\d*")) {
10 | txt.setText(oldValue);
11 | }
12 | });
13 | }
14 |
15 | public static void setTextFieldMaxLength(TextField txt, int max) {
16 | txt.textProperty().addListener((obs, oldValue, newValue) -> {
17 | if (newValue != null && newValue.length() > max) {
18 | txt.setText(oldValue);
19 | }
20 | });
21 | }
22 |
23 | public static void setTextFieldDouble(TextField txt) {
24 | txt.textProperty().addListener((obs, oldValue, newValue) -> {
25 | if (newValue != null && !newValue.matches("\\d*([\\.]\\d*)?")) {
26 | txt.setText(oldValue);
27 | }
28 | });
29 | }
30 | }
--------------------------------------------------------------------------------
/src/gui/util/Utils.java:
--------------------------------------------------------------------------------
1 | package gui.util;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.time.LocalDate;
5 | import java.time.format.DateTimeFormatter;
6 | import java.util.Date;
7 | import java.util.Locale;
8 |
9 | import javafx.event.ActionEvent;
10 | import javafx.scene.Node;
11 | import javafx.scene.control.DatePicker;
12 | import javafx.scene.control.TableCell;
13 | import javafx.scene.control.TableColumn;
14 | import javafx.stage.Stage;
15 | import javafx.util.StringConverter;
16 |
17 | public class Utils {
18 |
19 | public static Stage currentStage(ActionEvent event) {
20 | return (Stage) ((Node) event.getSource()).getScene().getWindow();
21 | }
22 |
23 | public static Integer tryParseToInt(String str) {
24 | try {
25 | return Integer.parseInt(str);
26 | } catch (NumberFormatException e) {
27 | return null;
28 | }
29 | }
30 |
31 | public static Double tryParseToDouble(String str) {
32 | try {
33 | return Double.parseDouble(str);
34 | } catch (NumberFormatException e) {
35 | return null;
36 | }
37 | }
38 |
39 | public static void formatTableColumnDate(TableColumn tableColumn, String format) {
40 | tableColumn.setCellFactory(column -> {
41 | TableCell cell = new TableCell() {
42 | private SimpleDateFormat sdf = new SimpleDateFormat(format);
43 |
44 | @Override
45 | protected void updateItem(Date item, boolean empty) {
46 | super.updateItem(item, empty);
47 | if (empty) {
48 | setText(null);
49 | } else {
50 | setText(sdf.format(item));
51 | }
52 | }
53 | };
54 | return cell;
55 | });
56 | }
57 |
58 | public static void formatTableColumnDouble(TableColumn tableColumn, int decimalPlaces) {
59 | tableColumn.setCellFactory(column -> {
60 | TableCell cell = new TableCell() {
61 | @Override
62 | protected void updateItem(Double item, boolean empty) {
63 | super.updateItem(item, empty);
64 | if (empty) {
65 | setText(null);
66 | } else {
67 | Locale.setDefault(Locale.US);
68 | setText(String.format("%." + decimalPlaces + "f", item));
69 | }
70 | }
71 | };
72 | return cell;
73 | });
74 | }
75 |
76 | public static void formatDatePicker(DatePicker datePicker, String format) {
77 | datePicker.setConverter(new StringConverter() {
78 | DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(format);
79 | {
80 | datePicker.setPromptText(format.toLowerCase());
81 | }
82 |
83 | @Override
84 | public String toString(LocalDate date) {
85 | if (date != null) {
86 | return dateFormatter.format(date);
87 | } else {
88 | return "";
89 | }
90 | }
91 |
92 | @Override
93 | public LocalDate fromString(String string) {
94 | if (string != null && !string.isEmpty()) {
95 | return LocalDate.parse(string, dateFormatter);
96 | } else {
97 | return null;
98 | }
99 | }
100 | });
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/model/dao/DaoFactory.java:
--------------------------------------------------------------------------------
1 | package model.dao;
2 |
3 | import db.DB;
4 | import model.dao.impl.DepartmentDaoJDBC;
5 | import model.dao.impl.SellerDaoJDBC;
6 |
7 | public class DaoFactory {
8 |
9 | public static SellerDao createSellerDao() {
10 | return new SellerDaoJDBC(DB.getConnection());
11 | }
12 |
13 | public static DepartmentDao createDepartmentDao() {
14 | return new DepartmentDaoJDBC(DB.getConnection());
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/model/dao/DepartmentDao.java:
--------------------------------------------------------------------------------
1 | package model.dao;
2 |
3 | import java.util.List;
4 |
5 | import model.entities.Department;
6 |
7 | public interface DepartmentDao {
8 |
9 | void insert(Department obj);
10 | void update(Department obj);
11 | void deleteById(Integer id);
12 | Department findById(Integer id);
13 | List findAll();
14 | }
15 |
--------------------------------------------------------------------------------
/src/model/dao/SellerDao.java:
--------------------------------------------------------------------------------
1 | package model.dao;
2 |
3 | import java.util.List;
4 |
5 | import model.entities.Department;
6 | import model.entities.Seller;
7 |
8 | public interface SellerDao {
9 |
10 | void insert(Seller obj);
11 | void update(Seller obj);
12 | void deleteById(Integer id);
13 | Seller findById(Integer id);
14 | List findAll();
15 | List findByDepartment(Department department);
16 | }
17 |
--------------------------------------------------------------------------------
/src/model/dao/impl/DepartmentDaoJDBC.java:
--------------------------------------------------------------------------------
1 | package model.dao.impl;
2 |
3 | import java.sql.Connection;
4 | import java.sql.PreparedStatement;
5 | import java.sql.ResultSet;
6 | import java.sql.SQLException;
7 | import java.sql.Statement;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | import db.DB;
12 | import db.DbException;
13 | import db.DbIntegrityException;
14 | import model.dao.DepartmentDao;
15 | import model.entities.Department;
16 |
17 | public class DepartmentDaoJDBC implements DepartmentDao {
18 |
19 | private Connection conn;
20 |
21 | public DepartmentDaoJDBC(Connection conn) {
22 | this.conn = conn;
23 | }
24 |
25 | @Override
26 | public Department findById(Integer id) {
27 | PreparedStatement st = null;
28 | ResultSet rs = null;
29 | try {
30 | st = conn.prepareStatement(
31 | "SELECT * FROM department WHERE Id = ?");
32 | st.setInt(1, id);
33 | rs = st.executeQuery();
34 | if (rs.next()) {
35 | Department obj = new Department();
36 | obj.setId(rs.getInt("Id"));
37 | obj.setName(rs.getString("Name"));
38 | return obj;
39 | }
40 | return null;
41 | }
42 | catch (SQLException e) {
43 | throw new DbException(e.getMessage());
44 | }
45 | finally {
46 | DB.closeStatement(st);
47 | DB.closeResultSet(rs);
48 | }
49 | }
50 |
51 | @Override
52 | public List findAll() {
53 | PreparedStatement st = null;
54 | ResultSet rs = null;
55 | try {
56 | st = conn.prepareStatement(
57 | "SELECT * FROM department ORDER BY Name");
58 | rs = st.executeQuery();
59 |
60 | List list = new ArrayList<>();
61 |
62 | while (rs.next()) {
63 | Department obj = new Department();
64 | obj.setId(rs.getInt("Id"));
65 | obj.setName(rs.getString("Name"));
66 | list.add(obj);
67 | }
68 | return list;
69 | }
70 | catch (SQLException e) {
71 | throw new DbException(e.getMessage());
72 | }
73 | finally {
74 | DB.closeStatement(st);
75 | DB.closeResultSet(rs);
76 | }
77 | }
78 |
79 | @Override
80 | public void insert(Department obj) {
81 | PreparedStatement st = null;
82 | try {
83 | st = conn.prepareStatement(
84 | "INSERT INTO department " +
85 | "(Name) " +
86 | "VALUES " +
87 | "(?)",
88 | Statement.RETURN_GENERATED_KEYS);
89 |
90 | st.setString(1, obj.getName());
91 |
92 | int rowsAffected = st.executeUpdate();
93 |
94 | if (rowsAffected > 0) {
95 | ResultSet rs = st.getGeneratedKeys();
96 | if (rs.next()) {
97 | int id = rs.getInt(1);
98 | obj.setId(id);
99 | }
100 | }
101 | else {
102 | throw new DbException("Unexpected error! No rows affected!");
103 | }
104 | }
105 | catch (SQLException e) {
106 | throw new DbException(e.getMessage());
107 | }
108 | finally {
109 | DB.closeStatement(st);
110 | }
111 | }
112 |
113 | @Override
114 | public void update(Department obj) {
115 | PreparedStatement st = null;
116 | try {
117 | st = conn.prepareStatement(
118 | "UPDATE department " +
119 | "SET Name = ? " +
120 | "WHERE Id = ?");
121 |
122 | st.setString(1, obj.getName());
123 | st.setInt(2, obj.getId());
124 |
125 | st.executeUpdate();
126 | }
127 | catch (SQLException e) {
128 | throw new DbException(e.getMessage());
129 | }
130 | finally {
131 | DB.closeStatement(st);
132 | }
133 | }
134 |
135 | @Override
136 | public void deleteById(Integer id) {
137 | PreparedStatement st = null;
138 | try {
139 | st = conn.prepareStatement(
140 | "DELETE FROM department WHERE Id = ?");
141 |
142 | st.setInt(1, id);
143 |
144 | st.executeUpdate();
145 | }
146 | catch (SQLException e) {
147 | throw new DbIntegrityException(e.getMessage());
148 | }
149 | finally {
150 | DB.closeStatement(st);
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/model/dao/impl/SellerDaoJDBC.java:
--------------------------------------------------------------------------------
1 | package model.dao.impl;
2 |
3 | import java.sql.Connection;
4 | import java.sql.PreparedStatement;
5 | import java.sql.ResultSet;
6 | import java.sql.SQLException;
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import com.mysql.jdbc.Statement;
13 |
14 | import db.DB;
15 | import db.DbException;
16 | import model.dao.SellerDao;
17 | import model.entities.Department;
18 | import model.entities.Seller;
19 |
20 | public class SellerDaoJDBC implements SellerDao {
21 |
22 | private Connection conn;
23 |
24 | public SellerDaoJDBC(Connection conn) {
25 | this.conn = conn;
26 | }
27 |
28 | @Override
29 | public void insert(Seller obj) {
30 | PreparedStatement st = null;
31 | try {
32 | st = conn.prepareStatement(
33 | "INSERT INTO seller "
34 | + "(Name, Email, BirthDate, BaseSalary, DepartmentId) "
35 | + "VALUES "
36 | + "(?, ?, ?, ?, ?)",
37 | Statement.RETURN_GENERATED_KEYS);
38 |
39 | st.setString(1, obj.getName());
40 | st.setString(2, obj.getEmail());
41 | st.setDate(3, new java.sql.Date(obj.getBirthDate().getTime()));
42 | st.setDouble(4, obj.getBaseSalary());
43 | st.setInt(5, obj.getDepartment().getId());
44 |
45 | int rowsAffected = st.executeUpdate();
46 |
47 | if (rowsAffected > 0) {
48 | ResultSet rs = st.getGeneratedKeys();
49 | if (rs.next()) {
50 | int id = rs.getInt(1);
51 | obj.setId(id);
52 | }
53 | DB.closeResultSet(rs);
54 | }
55 | else {
56 | throw new DbException("Unexpected error! No rows affected!");
57 | }
58 | }
59 | catch (SQLException e) {
60 | throw new DbException(e.getMessage());
61 | }
62 | finally {
63 | DB.closeStatement(st);
64 | }
65 | }
66 |
67 | @Override
68 | public void update(Seller obj) {
69 | PreparedStatement st = null;
70 | try {
71 | st = conn.prepareStatement(
72 | "UPDATE seller "
73 | + "SET Name = ?, Email = ?, BirthDate = ?, BaseSalary = ?, DepartmentId = ? "
74 | + "WHERE Id = ?");
75 |
76 | st.setString(1, obj.getName());
77 | st.setString(2, obj.getEmail());
78 | st.setDate(3, new java.sql.Date(obj.getBirthDate().getTime()));
79 | st.setDouble(4, obj.getBaseSalary());
80 | st.setInt(5, obj.getDepartment().getId());
81 | st.setInt(6, obj.getId());
82 |
83 | st.executeUpdate();
84 | }
85 | catch (SQLException e) {
86 | throw new DbException(e.getMessage());
87 | }
88 | finally {
89 | DB.closeStatement(st);
90 | }
91 | }
92 |
93 | @Override
94 | public void deleteById(Integer id) {
95 | PreparedStatement st = null;
96 | try {
97 | st = conn.prepareStatement("DELETE FROM seller WHERE Id = ?");
98 |
99 | st.setInt(1, id);
100 |
101 | st.executeUpdate();
102 | }
103 | catch (SQLException e) {
104 | throw new DbException(e.getMessage());
105 | }
106 | finally {
107 | DB.closeStatement(st);
108 | }
109 | }
110 |
111 | @Override
112 | public Seller findById(Integer id) {
113 | PreparedStatement st = null;
114 | ResultSet rs = null;
115 | try {
116 | st = conn.prepareStatement(
117 | "SELECT seller.*,department.Name as DepName "
118 | + "FROM seller INNER JOIN department "
119 | + "ON seller.DepartmentId = department.Id "
120 | + "WHERE seller.Id = ?");
121 |
122 | st.setInt(1, id);
123 | rs = st.executeQuery();
124 | if (rs.next()) {
125 | Department dep = instantiateDepartment(rs);
126 | Seller obj = instantiateSeller(rs, dep);
127 | return obj;
128 | }
129 | return null;
130 | }
131 | catch (SQLException e) {
132 | throw new DbException(e.getMessage());
133 | }
134 | finally {
135 | DB.closeStatement(st);
136 | DB.closeResultSet(rs);
137 | }
138 | }
139 |
140 | private Seller instantiateSeller(ResultSet rs, Department dep) throws SQLException {
141 | Seller obj = new Seller();
142 | obj.setId(rs.getInt("Id"));
143 | obj.setName(rs.getString("Name"));
144 | obj.setEmail(rs.getString("Email"));
145 | obj.setBaseSalary(rs.getDouble("BaseSalary"));
146 | obj.setBirthDate(new java.util.Date(rs.getTimestamp("BirthDate").getTime()));
147 | obj.setDepartment(dep);
148 | return obj;
149 | }
150 |
151 | private Department instantiateDepartment(ResultSet rs) throws SQLException {
152 | Department dep = new Department();
153 | dep.setId(rs.getInt("DepartmentId"));
154 | dep.setName(rs.getString("DepName"));
155 | return dep;
156 | }
157 |
158 | @Override
159 | public List findAll() {
160 | PreparedStatement st = null;
161 | ResultSet rs = null;
162 | try {
163 | st = conn.prepareStatement(
164 | "SELECT seller.*,department.Name as DepName "
165 | + "FROM seller INNER JOIN department "
166 | + "ON seller.DepartmentId = department.Id "
167 | + "ORDER BY Name");
168 |
169 | rs = st.executeQuery();
170 |
171 | List list = new ArrayList<>();
172 | Map map = new HashMap<>();
173 |
174 | while (rs.next()) {
175 |
176 | Department dep = map.get(rs.getInt("DepartmentId"));
177 |
178 | if (dep == null) {
179 | dep = instantiateDepartment(rs);
180 | map.put(rs.getInt("DepartmentId"), dep);
181 | }
182 |
183 | Seller obj = instantiateSeller(rs, dep);
184 | list.add(obj);
185 | }
186 | return list;
187 | }
188 | catch (SQLException e) {
189 | throw new DbException(e.getMessage());
190 | }
191 | finally {
192 | DB.closeStatement(st);
193 | DB.closeResultSet(rs);
194 | }
195 | }
196 |
197 | @Override
198 | public List findByDepartment(Department department) {
199 | PreparedStatement st = null;
200 | ResultSet rs = null;
201 | try {
202 | st = conn.prepareStatement(
203 | "SELECT seller.*,department.Name as DepName "
204 | + "FROM seller INNER JOIN department "
205 | + "ON seller.DepartmentId = department.Id "
206 | + "WHERE DepartmentId = ? "
207 | + "ORDER BY Name");
208 |
209 | st.setInt(1, department.getId());
210 |
211 | rs = st.executeQuery();
212 |
213 | List list = new ArrayList<>();
214 | Map map = new HashMap<>();
215 |
216 | while (rs.next()) {
217 |
218 | Department dep = map.get(rs.getInt("DepartmentId"));
219 |
220 | if (dep == null) {
221 | dep = instantiateDepartment(rs);
222 | map.put(rs.getInt("DepartmentId"), dep);
223 | }
224 |
225 | Seller obj = instantiateSeller(rs, dep);
226 | list.add(obj);
227 | }
228 | return list;
229 | }
230 | catch (SQLException e) {
231 | throw new DbException(e.getMessage());
232 | }
233 | finally {
234 | DB.closeStatement(st);
235 | DB.closeResultSet(rs);
236 | }
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/src/model/entities/Department.java:
--------------------------------------------------------------------------------
1 | package model.entities;
2 |
3 | import java.io.Serializable;
4 |
5 | public class Department implements Serializable {
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | private Integer id;
10 | private String name;
11 |
12 | public Department() {
13 | }
14 |
15 | public Department(Integer id, String name) {
16 | this.id = id;
17 | this.name = name;
18 | }
19 |
20 | public Integer getId() {
21 | return id;
22 | }
23 |
24 | public void setId(Integer id) {
25 | this.id = id;
26 | }
27 |
28 | public String getName() {
29 | return name;
30 | }
31 |
32 | public void setName(String name) {
33 | this.name = name;
34 | }
35 |
36 | @Override
37 | public int hashCode() {
38 | final int prime = 31;
39 | int result = 1;
40 | result = prime * result + ((id == null) ? 0 : id.hashCode());
41 | return result;
42 | }
43 |
44 | @Override
45 | public boolean equals(Object obj) {
46 | if (this == obj)
47 | return true;
48 | if (obj == null)
49 | return false;
50 | if (getClass() != obj.getClass())
51 | return false;
52 | Department other = (Department) obj;
53 | if (id == null) {
54 | if (other.id != null)
55 | return false;
56 | } else if (!id.equals(other.id))
57 | return false;
58 | return true;
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return "Department [id=" + id + ", name=" + name + "]";
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/model/entities/Seller.java:
--------------------------------------------------------------------------------
1 | package model.entities;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | public class Seller implements Serializable {
7 |
8 | private static final long serialVersionUID = 1L;
9 |
10 | private Integer id;
11 | private String name;
12 | private String email;
13 | private Date birthDate;
14 | private Double baseSalary;
15 |
16 | private Department department;
17 |
18 | public Seller() {
19 | }
20 |
21 | public Seller(Integer id, String name, String email, Date birthDate, Double baseSalary, Department department) {
22 | this.id = id;
23 | this.name = name;
24 | this.email = email;
25 | this.birthDate = birthDate;
26 | this.baseSalary = baseSalary;
27 | this.department = department;
28 | }
29 |
30 | public Integer getId() {
31 | return id;
32 | }
33 |
34 | public void setId(Integer id) {
35 | this.id = id;
36 | }
37 |
38 | public String getName() {
39 | return name;
40 | }
41 |
42 | public void setName(String name) {
43 | this.name = name;
44 | }
45 |
46 | public String getEmail() {
47 | return email;
48 | }
49 |
50 | public void setEmail(String email) {
51 | this.email = email;
52 | }
53 |
54 | public Date getBirthDate() {
55 | return birthDate;
56 | }
57 |
58 | public void setBirthDate(Date birthDate) {
59 | this.birthDate = birthDate;
60 | }
61 |
62 | public Double getBaseSalary() {
63 | return baseSalary;
64 | }
65 |
66 | public void setBaseSalary(Double baseSalary) {
67 | this.baseSalary = baseSalary;
68 | }
69 |
70 | public Department getDepartment() {
71 | return department;
72 | }
73 |
74 | public void setDepartment(Department department) {
75 | this.department = department;
76 | }
77 |
78 | @Override
79 | public int hashCode() {
80 | final int prime = 31;
81 | int result = 1;
82 | result = prime * result + ((id == null) ? 0 : id.hashCode());
83 | return result;
84 | }
85 |
86 | @Override
87 | public boolean equals(Object obj) {
88 | if (this == obj)
89 | return true;
90 | if (obj == null)
91 | return false;
92 | if (getClass() != obj.getClass())
93 | return false;
94 | Seller other = (Seller) obj;
95 | if (id == null) {
96 | if (other.id != null)
97 | return false;
98 | } else if (!id.equals(other.id))
99 | return false;
100 | return true;
101 | }
102 |
103 | @Override
104 | public String toString() {
105 | return "Seller [id=" + id + ", name=" + name + ", email=" + email + ", birthDate=" + birthDate + ", baseSalary="
106 | + baseSalary + ", department=" + department + "]";
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/model/exceptions/ValidationException.java:
--------------------------------------------------------------------------------
1 | package model.exceptions;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class ValidationException extends RuntimeException {
7 |
8 | private static final long serialVersionUID = 1L;
9 |
10 | private Map errors = new HashMap<>();
11 |
12 | public ValidationException(String msg) {
13 | super(msg);
14 | }
15 |
16 | public Map getErrors() {
17 | return errors;
18 | }
19 |
20 | public void addError(String fieldName, String errorMessage) {
21 | errors.put(fieldName, errorMessage);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/model/services/DepartmentService.java:
--------------------------------------------------------------------------------
1 | package model.services;
2 |
3 | import java.util.List;
4 |
5 | import model.dao.DaoFactory;
6 | import model.dao.DepartmentDao;
7 | import model.entities.Department;
8 |
9 | public class DepartmentService {
10 |
11 | private DepartmentDao dao = DaoFactory.createDepartmentDao();
12 |
13 | public List findAll() {
14 | return dao.findAll();
15 | }
16 |
17 | public void saveOrUpdate(Department obj) {
18 | if (obj.getId() == null) {
19 | dao.insert(obj);
20 | }
21 | else {
22 | dao.update(obj);
23 | }
24 | }
25 |
26 | public void remove(Department obj) {
27 | dao.deleteById(obj.getId());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/model/services/SellerService.java:
--------------------------------------------------------------------------------
1 | package model.services;
2 |
3 | import java.util.List;
4 |
5 | import model.dao.DaoFactory;
6 | import model.dao.SellerDao;
7 | import model.entities.Seller;
8 |
9 | public class SellerService {
10 |
11 | private SellerDao dao = DaoFactory.createSellerDao();
12 |
13 | public List findAll() {
14 | return dao.findAll();
15 | }
16 |
17 | public void saveOrUpdate(Seller obj) {
18 | if (obj.getId() == null) {
19 | dao.insert(obj);
20 | }
21 | else {
22 | dao.update(obj);
23 | }
24 | }
25 |
26 | public void remove(Seller obj) {
27 | dao.deleteById(obj.getId());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------