-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Solve exercise 29.3 - Address Book Modification: Delete an Existing
Entry
- Loading branch information
Guto Alves
committed
Jul 21, 2020
1 parent
f963f82
commit 38dbe14
Showing
6 changed files
with
333 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<?import javafx.geometry.Insets?> | ||
<?import javafx.scene.control.Button?> | ||
<?import javafx.scene.control.Label?> | ||
<?import javafx.scene.control.ListView?> | ||
<?import javafx.scene.control.Separator?> | ||
<?import javafx.scene.control.TextField?> | ||
<?import javafx.scene.control.ToolBar?> | ||
<?import javafx.scene.layout.BorderPane?> | ||
<?import javafx.scene.layout.ColumnConstraints?> | ||
<?import javafx.scene.layout.GridPane?> | ||
<?import javafx.scene.layout.HBox?> | ||
<?import javafx.scene.layout.RowConstraints?> | ||
<?import javafx.scene.layout.VBox?> | ||
|
||
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch29.ex29_03.AddressBookController"> | ||
<bottom> | ||
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER"> | ||
<items> | ||
<Label text="Find by last name:" /> | ||
<TextField fx:id="findByLastNameTextField" /> | ||
<Button mnemonicParsing="false" onAction="#findButtonPressed" text="Find" /> | ||
<Separator orientation="VERTICAL" /> | ||
<Button mnemonicParsing="false" onAction="#browseAllButtonPressed" text="Browse All" /> | ||
</items> | ||
</ToolBar> | ||
</bottom> | ||
<left> | ||
<ListView fx:id="listView" prefWidth="160.0" BorderPane.alignment="CENTER" /> | ||
</left> | ||
<center> | ||
<VBox prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER"> | ||
<children> | ||
<GridPane alignment="CENTER" hgap="8.0" vgap="8.0"> | ||
<columnConstraints> | ||
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" /> | ||
<ColumnConstraints hgrow="SOMETIMES" /> | ||
</columnConstraints> | ||
<rowConstraints> | ||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> | ||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> | ||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> | ||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> | ||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> | ||
</rowConstraints> | ||
<children> | ||
<Label text="First name:" /> | ||
<Label text="Last name:" GridPane.rowIndex="1" /> | ||
<Label text="Email:" GridPane.rowIndex="2" /> | ||
<Label text="Phone:" GridPane.rowIndex="3" /> | ||
<TextField fx:id="firstNameTextField" prefColumnCount="25" GridPane.columnIndex="1" /> | ||
<TextField fx:id="lastNameTextField" maxWidth="1.7976931348623157E308" prefColumnCount="25" GridPane.columnIndex="1" GridPane.rowIndex="1" /> | ||
<TextField fx:id="emailTextField" maxWidth="1.7976931348623157E308" prefColumnCount="25" GridPane.columnIndex="1" GridPane.rowIndex="2" /> | ||
<TextField fx:id="phoneTextField" maxWidth="1.7976931348623157E308" prefColumnCount="25" GridPane.columnIndex="1" GridPane.rowIndex="3" /> | ||
<HBox alignment="CENTER_RIGHT" prefHeight="100.0" prefWidth="200.0" spacing="8.0" GridPane.columnIndex="1" GridPane.rowIndex="4"> | ||
<children> | ||
<Button mnemonicParsing="false" onAction="#clearSelectionButtonPressed" text="Clear" /> | ||
<Button mnemonicParsing="false" onAction="#deleteEntryButtonPressed" text="Delete Entry" /> | ||
<Button mnemonicParsing="false" onAction="#updateEntryButtonPressed" text="Update Entry" /> | ||
<Button mnemonicParsing="false" onAction="#addEntryButtonPressed" text="Add Entry" /> | ||
</children> | ||
</HBox> | ||
</children> | ||
<VBox.margin> | ||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" /> | ||
</VBox.margin> | ||
</GridPane> | ||
</children> | ||
</VBox> | ||
</center> | ||
</BorderPane> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Main application class that loads and displays the AddressBook's GUI. | ||
|
||
package ch29.ex29_03; | ||
|
||
import javafx.application.Application; | ||
import javafx.fxml.FXMLLoader; | ||
import javafx.scene.Parent; | ||
import javafx.scene.Scene; | ||
import javafx.stage.Stage; | ||
|
||
public class AddressBook extends Application { | ||
@Override | ||
public void start(Stage stage) throws Exception { | ||
Parent root = | ||
FXMLLoader.load(getClass().getResource("AddressBook.fxml")); | ||
|
||
Scene scene = new Scene(root); | ||
stage.setTitle("Address Book"); | ||
stage.setScene(scene); | ||
stage.show(); | ||
} | ||
|
||
public static void main(String[] args) { | ||
launch(args); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
// Fig. 29.4: AddressBookController.java | ||
// Controller for a simple address book | ||
|
||
package ch29.ex29_03; | ||
|
||
import java.util.List; | ||
import javafx.collections.FXCollections; | ||
import javafx.collections.ObservableList; | ||
import javafx.event.ActionEvent; | ||
import javafx.fxml.FXML; | ||
import javafx.scene.control.Alert; | ||
import javafx.scene.control.Alert.AlertType; | ||
import javafx.scene.control.ListView; | ||
import javafx.scene.control.TextField; | ||
import javax.persistence.EntityManager; | ||
import javax.persistence.EntityManagerFactory; | ||
import javax.persistence.EntityTransaction; | ||
import javax.persistence.Persistence; | ||
import javax.persistence.TypedQuery; | ||
|
||
import ch29.ex29_02.Addresses; | ||
|
||
public class AddressBookController { | ||
@FXML | ||
private ListView<Addresses> listView; | ||
@FXML | ||
private TextField firstNameTextField; | ||
@FXML | ||
private TextField lastNameTextField; | ||
@FXML | ||
private TextField emailTextField; | ||
@FXML | ||
private TextField phoneTextField; | ||
@FXML | ||
private TextField findByLastNameTextField; | ||
|
||
// create an EntityManagerFactory for the persistence unit | ||
private final EntityManagerFactory entityManagerFactory = | ||
Persistence.createEntityManagerFactory("AddressBookPU"); | ||
|
||
// create an EntityManager for interacting with the persistence unit | ||
private final EntityManager entityManager = | ||
entityManagerFactory.createEntityManager(); | ||
|
||
// stores list of Addresses objects that results from a database query | ||
private final ObservableList<Addresses> contactList = | ||
FXCollections.observableArrayList(); | ||
|
||
// populate listView and set up listener for selection events | ||
public void initialize() { | ||
listView.setItems(contactList); // bind to contactsList | ||
|
||
// when ListView selection changes, display selected person's data | ||
listView.getSelectionModel().selectedItemProperty().addListener( | ||
(observableValue, oldValue, newValue) -> { | ||
displayContact(newValue); | ||
}); | ||
getAllEntries(); // populates contactList, which updates listView | ||
} | ||
|
||
// get all the entries from the database to populate contactList | ||
private void getAllEntries() { | ||
// query that returns all contacts | ||
TypedQuery<Addresses> findAllAddresses = | ||
entityManager.createNamedQuery( | ||
"Addresses.findAll", Addresses.class); | ||
|
||
contactList.setAll(findAllAddresses.getResultList()); | ||
selectFirstEntry(); | ||
} | ||
|
||
// select first item in listView | ||
private void selectFirstEntry() { | ||
listView.getSelectionModel().selectFirst(); | ||
} | ||
|
||
// display contact information | ||
private void displayContact(Addresses contact) { | ||
if (contact != null) { | ||
firstNameTextField.setText(contact.getFirstname()); | ||
lastNameTextField.setText(contact.getLastname()); | ||
emailTextField.setText(contact.getEmail()); | ||
phoneTextField.setText(contact.getPhonenumber()); | ||
} else { | ||
firstNameTextField.clear(); | ||
lastNameTextField.clear(); | ||
emailTextField.clear(); | ||
phoneTextField.clear(); | ||
} | ||
} | ||
|
||
// add a new entry | ||
@FXML | ||
void addEntryButtonPressed(ActionEvent event) { | ||
if (lastNameTextField.getText().isBlank()) { | ||
displayAlert(AlertType.ERROR, "Entry Not Added", | ||
"Last name field is required."); | ||
return; | ||
} | ||
|
||
Addresses address = new Addresses(); | ||
address.setFirstname(firstNameTextField.getText()); | ||
address.setLastname(lastNameTextField.getText()); | ||
address.setPhonenumber(phoneTextField.getText()); | ||
address.setEmail(emailTextField.getText()); | ||
|
||
// get an EntityTransaction to manage insert operation | ||
EntityTransaction transaction = entityManager.getTransaction(); | ||
|
||
try { | ||
transaction.begin(); // start transaction | ||
entityManager.persist(address); // store new entry | ||
transaction.commit(); // commit changes to the database | ||
displayAlert(AlertType.INFORMATION, "Entry Added", | ||
"New entry successfully added."); | ||
getAllEntries(); | ||
} catch (Exception e) {// if transaction failed | ||
transaction.rollback(); // undo database operations | ||
displayAlert(AlertType.ERROR, "Entry Not Added", | ||
"Unable to add entry: " + e); | ||
} | ||
} | ||
|
||
@FXML | ||
void updateEntryButtonPressed(ActionEvent event) { | ||
if (lastNameTextField.getText().isBlank()) { | ||
displayAlert(AlertType.ERROR, "Entry Not Updated", | ||
"Last name field is required."); | ||
return; | ||
} | ||
|
||
EntityTransaction entityTransaction = | ||
entityManager.getTransaction(); | ||
|
||
try { | ||
entityTransaction.begin(); | ||
Addresses address = | ||
listView.getSelectionModel().getSelectedItem(); | ||
address.setFirstname(firstNameTextField.getText()); | ||
address.setLastname(lastNameTextField.getText()); | ||
address.setPhonenumber(phoneTextField.getText()); | ||
address.setEmail(emailTextField.getText()); | ||
entityTransaction.commit(); | ||
|
||
getAllEntries(); | ||
listView.getSelectionModel().select(address); | ||
} catch (Exception e) { | ||
entityTransaction.rollback(); | ||
displayAlert(AlertType.ERROR, "Entry Not Updated", | ||
"Unable to update entry: " + e); | ||
} | ||
} | ||
|
||
@FXML | ||
void deleteEntryButtonPressed(ActionEvent event) { | ||
EntityTransaction entityTransaction = | ||
entityManager.getTransaction(); | ||
try { | ||
entityTransaction.begin(); | ||
entityManager.remove(listView.getSelectionModel().getSelectedItem()); | ||
entityTransaction.commit(); | ||
getAllEntries(); | ||
selectFirstEntry(); | ||
} catch (Exception e) { | ||
entityTransaction.rollback(); | ||
displayAlert(AlertType.ERROR, "Entry Not Deleted", | ||
"Unable to delete entry: " + e); | ||
} | ||
} | ||
|
||
@FXML | ||
void clearSelectionButtonPressed(ActionEvent event) { | ||
listView.getSelectionModel().clearSelection(); | ||
} | ||
|
||
// find entries with the specified last name | ||
@FXML | ||
void findButtonPressed(ActionEvent event) { | ||
// query that returns all contacts | ||
TypedQuery<Addresses> findByLastname = | ||
entityManager.createNamedQuery("Addresses.findByLastname", | ||
Addresses.class); | ||
|
||
// configure parameter for query | ||
findByLastname.setParameter( | ||
"lastname", findByLastNameTextField.getText() + "%"); | ||
|
||
// get all addresses | ||
List<Addresses> people = findByLastname.getResultList(); | ||
|
||
if (people.size() > 0) { // display all entries | ||
contactList.setAll(people); | ||
selectFirstEntry(); | ||
} else { | ||
displayAlert(AlertType.INFORMATION, "Lastname Not Found", | ||
"There are no entries with the specified last name."); | ||
} | ||
} | ||
|
||
// browse all the entries | ||
@FXML | ||
void browseAllButtonPressed(ActionEvent event) { | ||
getAllEntries(); | ||
} | ||
|
||
// display an Alert dialog | ||
private void displayAlert(AlertType type, String title, | ||
String message) { | ||
Alert alert = new Alert(type); | ||
alert.setTitle(title); | ||
alert.setContentText(message); | ||
alert.showAndWait(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
DROP TABLE Addresses; | ||
|
||
CREATE TABLE Addresses | ||
( | ||
AddressID INT NOT NULL GENERATED ALWAYS AS IDENTITY, | ||
FirstName VARCHAR (15) NOT NULL, | ||
LastName VARCHAR (30) NOT NULL, | ||
Email VARCHAR (30) NOT NULL, | ||
PhoneNumber VARCHAR (15) NOT NULL, | ||
PRIMARY KEY (AddressID) | ||
); | ||
|
||
INSERT INTO Addresses (FirstName,LastName,Email,PhoneNumber) | ||
VALUES ('Mike','Green','[email protected]','555-5555'), | ||
('Mary','Brown','[email protected]','555-1234'); |