Commit 5d9a1ae3 authored by Arne Styve's avatar Arne Styve
Browse files

Renamed AddressBookDAO to AddressBookDBHandler. Changed the initialisation and...

Renamed AddressBookDAO to AddressBookDBHandler. Changed the initialisation and use of EntityManager from being a field instantiated once, to be instantiated locally per use.
parent a0d64217
......@@ -12,6 +12,7 @@ The project was developed for use in teaching in the course "IDATx2001 Programme
**Version** | **Description**
--------|------------
v0.4.1 | Renamed the class AddressBookDAO to AddressBookDBHandler, since DAO is a general term that also could be used for the AddressBookFileHandler. Also altered slightly the use of EntityManager.
v0.4 | Added Relational Database support, using the embedded Apache Derby server. For details of the changes made, se below.
v0.3 | Adds object serialization of the entire address book.
v0.2 | Added import and export from/to CSV-file. A default CSV-file is provided (Addresses.csv)
......
......@@ -18,6 +18,13 @@
<property name="eclipselink.ddl-generation" value="create-tables"/>
<!-- Alternatives: FINE (logs all SQL), ALL, CONFIG, INFO, WARNING..., OFF -->
<property name="eclipselink.logging.level" value="FINE"/>
<!--
The Database can be pre-filled with entries during startup. This would be very useful during testing
of the application, used in conjunction with "drop-and-create-tables". The SQL-statements for inserting
entries in the DB-table can be stored in a text-file. The line below, when un-commented, will
read SQL-statements from the file "META-INF/sql/data.sql" during application startup.
-->
<!--property name="javax.persistence.sql-load-script-source" value="META-INF/sql/data.sql"/-->
</properties>
......
......@@ -19,7 +19,7 @@ import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.util.Pair;
import no.ntnu.idata2001.contacts.model.AddressBook;
import no.ntnu.idata2001.contacts.model.AddressBookDAO;
import no.ntnu.idata2001.contacts.model.AddressBookDBHandler;
import no.ntnu.idata2001.contacts.model.AddressBookFileHandler;
import no.ntnu.idata2001.contacts.model.ContactDetails;
import no.ntnu.idata2001.contacts.views.ContactDetailsDialog;
......@@ -212,7 +212,7 @@ public class MainController {
* @return an address book populated by contact details loaded from the database.
*/
public AddressBook loadAddressBookFromDB() {
return new AddressBookDAO();
return new AddressBookDBHandler();
}
/**
......
package no.ntnu.idata2001.contacts.model;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class AddressBookDAO implements AddressBook {
// Note the 'transient'-keyword. This is to indicate that these fields
/**
* An addressbook holding contacts, stored in a relational database, implemented using
* the JPA implementation EclipseLink.
* Using the JPA standard for Object Relational Mapping (ORM) removes database specifics
* from the Java code, and hides the underlying RDB solution, making it easy to change between
* different suppliers of Relational Database management Systems (RDBMS), and between locally
* embedded database and server based database systems.
* JPA makes use of <b>EntityManager</b> (EMF) and <b>EntityManagerFactory</b> (EM) classes for
* communication with the underlying RDBMS. Creating an EntityManagerFactory instance is costly:
* </p>
* (<a href="https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html_single/#d0e980">
* "An entity manager factory is typically create at application initialization time and closed at
* * application end. It's creation is an expensive process."</a>
* </p>
* Hence the EMF is implemented as a field in this class.
*
* <b>NOTE:</b> While the EMF is <b>thread safe</b>, the EM is <b>not thread safe</b>.
*/
public class AddressBookDBHandler implements AddressBook {
// Note the 'transient'-keyword. This is to indicate that this field
// should never be serialized. Since the AddressBook-interface
// implements Serializable (used for object serialisation), this class
// to is tagged to be serializable. But the two fields in this class is used to
// communicate with the database, and should hence not be serialized. Neither are
// the classes EntityManager nor EntityManagerFactory serializable.
// too is tagged to be serializable. But the field in this class is used to
// communicate with the database, and should hence not be serialized.
private final transient EntityManagerFactory efact;
private final transient EntityManager eman;
/**
* Creates an instance of the AddressbookDAO.
*/
public AddressBookDAO() {
public AddressBookDBHandler() {
this.efact = Persistence.createEntityManagerFactory("contacts-pu");
this.eman = efact.createEntityManager();
}
@Override
public ContactDetails findContactByPhoneNumber(String phoneNumber) {
//TODO: To be implemented later....
return null;
}
......@@ -39,9 +56,11 @@ public class AddressBookDAO implements AddressBook {
@Override
public void addContact(ContactDetails contact) {
this.eman.getTransaction().begin();
this.eman.persist(contact);
this.eman.getTransaction().commit();
EntityManager eman = this.efact.createEntityManager();
eman.getTransaction().begin();
eman.persist(contact);
eman.getTransaction().commit();
eman.close();
}
@Override
......@@ -61,6 +80,7 @@ public class AddressBookDAO implements AddressBook {
@Override
public Collection<ContactDetails> getAllContacts() {
EntityManager eman = this.efact.createEntityManager();
List<ContactDetails> contactsList = null;
......@@ -69,17 +89,18 @@ public class AddressBookDAO implements AddressBook {
Query query = eman.createQuery(sql);
contactsList = query.getResultList();
eman.close();
return contactsList;
}
@Override
public void close() {
this.eman.close();
this.efact.close();
}
@Override
public Iterator<ContactDetails> iterator() {
public synchronized Iterator<ContactDetails> iterator() {
return getAllContacts().iterator();
}
}
......@@ -140,8 +140,7 @@ public class ContactDetailsDialog extends Dialog<ContactDetails> {
getDialogPane().setContent(grid);
// Convert the result to ContactDetails-instance when the OK button is clicked.
// Check out: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html#setResultConverter-javafx.util.Callback-
// and: https://docs.oracle.com/javase/8/javafx/api/javafx/util/Callback.html
// Check: https://docs.oracle.com/javase/8/javafx/api/javafx/util/Callback.html
setResultConverter(
(ButtonType button) -> {
ContactDetails result = null;
......
......@@ -61,7 +61,6 @@ public class ContactsApp extends Application {
this.mainController = new MainController();
// Initialise the Address Book from a file
//this.addressBook = this.mainController.loadAddressBookFromFile();
this.addressBook = this.mainController.loadAddressBookFromDB();
}
......@@ -105,8 +104,6 @@ public class ContactsApp extends Application {
*/
@Override
public void stop() {
// Save the address book to file
//this.mainController.saveAddressBookToFile(this.addressBook);
// Exit the application
System.exit(0);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment