Browse Source

Database support.

Tankernn 8 years ago
parent
commit
061a4a6fac

BIN
data/accounts.acc


BIN
data/backup.scc


+ 38 - 0
formats.md

@@ -0,0 +1,38 @@
+# Definition of data structure formats.
+
+## Current:
+
+Account
+* First Name
+* Last Name
+* Account Number
+* History
+
+Account Event
+* Balance Change
+* Description
+
+### SQL
+Accounts
+FirstName | LastName | AccountNumber | History (JSON text)
+
+## Optimal:
+
+Account
+* First Name
+* Last Name
+* Account Number (indentifier)
+
+Account Event
+* Type (transfer | deposit | withdrawal)
+* Receiver (if applicable)
+* Sender (if applicable)
+* Balance Change
+* // Description can be generated based on available info
+
+### SQL
+Accounts
+FirstName | LastName | AccountNumber
+
+Events
+Type (int) | Receiver (accountnumber) | Sender (accountnumber) | BalanceChange (double)

+ 5 - 0
pom.xml

@@ -20,6 +20,11 @@
 			<artifactId>commons-codec</artifactId>
 			<version>1.9</version>
 		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>5.1.39</version>
+		</dependency>
 	</dependencies>
 
 	<build>

+ 8 - 1
src/eu/tankernn/accounts/Account.java

@@ -7,8 +7,8 @@ import java.util.List;
 
 public class Account {
 	
-	private List<AccountEvent> history;
 	private String firstName, lastName, accountNumber;
+	private List<AccountEvent> history;
 
 	public Account(String firstName, String lastName) {
 		// Generate a random, unique account id
@@ -19,6 +19,13 @@ public class Account {
 		this.lastName = lastName;
 		this.history = new ArrayList<AccountEvent>();
 	}
+	
+	Account(String firstName, String lastName, String accountNumber, List<AccountEvent> history) {
+		this.firstName = firstName;
+		this.lastName = lastName;
+		this.accountNumber = accountNumber;
+		this.history = history;
+	}
 
 	public String getFirstName() {
 		return firstName;

+ 1 - 1
src/eu/tankernn/accounts/AccountEvent.java

@@ -17,7 +17,7 @@ public class AccountEvent {
 	 * @param balanceChange The change in account balance.
 	 * @param descriptionFormat
 	 *            A string that will be used for a <code>String.format()</code>
-	 *            call, along with the absolute balance chage value.
+	 *            call, along with the absolute balance change value.
 	 */
 	public AccountEvent(double balanceChange, String descriptionFormat) {
 		this.balanceChange = balanceChange;

+ 7 - 4
src/eu/tankernn/accounts/AccountManager.java

@@ -122,6 +122,7 @@ public class AccountManager {
 
 		accounts.clear();
 		lastJSONString = exportJSON();
+		window.refresh();
 	}
 
 	/**
@@ -161,9 +162,7 @@ public class AccountManager {
 	 *         otherwise.
 	 */
 	public static boolean closeFile() {
-		if (!AccountManager.hasUnsavedChanges()) {
-			return true;
-		} else {
+		if (AccountManager.hasUnsavedChanges()) {
 			int option = JOptionPane.showOptionDialog(null, "Would you like to save changes before exit?",
 					"Save changes", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, 0);
 
@@ -174,12 +173,16 @@ public class AccountManager {
 				} catch (FileNotFoundException e) {
 					e.printStackTrace();
 				}
+				break;
 			case JOptionPane.NO_OPTION:
-				return true;
+				break;
 			default:
 				return false;
 			}
 		}
+		accounts.clear();
+		window.refresh();
+		return true;
 	}
 
 	private static List<Account> parseJSON(String jsonString) {

+ 97 - 10
src/eu/tankernn/accounts/DBManager.java

@@ -2,30 +2,117 @@ package eu.tankernn.accounts;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
 
 public class DBManager {
 	// JDBC driver name and database URL
-	static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
-	static final String DB_URL = "jdbc:mysql://tankernn.eu/EMP";
+	private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
+	private static final String DB_URL = "jdbc:mysql://localhost/AccountManager";
 
 	// Database credentials
-	static final String USER = "AccountManager";
-	static final String PASS = "laUqy\\%]aeOe";
+	private static final String USER = "root";
+	private static final String PASS = "password";
 
-	static Connection conn = null;
-	static Statement stmt = null;
+	private static Connection conn = null;
+	private static Statement stmt = null;
 
 	public static void init() {
+		if (inited()) // Already inited
+			return;
 		try {
-			Class.forName("com.mysql.jdbc.Driver");
-			conn = DriverManager.getConnection(DB_URL,USER,PASS);
+			Class.forName(JDBC_DRIVER);
+			conn = DriverManager.getConnection(DB_URL, USER, PASS);
+
+			// Check if table exists and create it otherwise
+			stmt = conn.createStatement();
+			conn.createStatement().executeUpdate(
+					"CREATE TABLE IF NOT EXISTS Accounts (FirstName varchar(255), LastName varchar(255), AccountNumber varchar(30) NOT NULL UNIQUE, PRIMARY KEY (AccountNumber))");
+			conn.createStatement().executeUpdate(
+					"CREATE TABLE IF NOT EXISTS Events (uid int AUTO_INCREMENT UNIQUE, account varchar(255), balanceChange double, description varchar(512), PRIMARY KEY (uid))");
 		} catch (SQLException | ClassNotFoundException e) {
 			e.printStackTrace();
 			return;
 		}
 	}
-	
-	
+
+	public static void saveAccounts(List<Account> accounts) {
+		try {
+			conn.createStatement().executeUpdate("DELETE FROM Events");
+		} catch (SQLException e1) {
+			e1.printStackTrace();
+		}
+		for (Account a : accounts) {
+			try {
+				PreparedStatement ps = conn.prepareStatement(
+						"INSERT IGNORE INTO Accounts (firstName, lastName, accountNumber) VALUES (?, ?, ?)");
+				ps.setString(1, a.getFirstName());
+				ps.setString(2, a.getLastName());
+				ps.setString(3, a.getAccountNumber());
+				saveAccountEvents(a.getAccountNumber(), a.getHistory());
+				ps.executeUpdate();
+			} catch (SQLException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private static List<AccountEvent> getAccountEvents(String accountNumber) {
+		try {
+			PreparedStatement ps = conn.prepareStatement("SELECT * FROM Events WHERE account=?");
+			ps.setString(1, accountNumber);
+			ResultSet set = ps.executeQuery();
+			List<AccountEvent> events = new ArrayList<AccountEvent>();
+			while (set.next()) {
+				events.add(new AccountEvent(set.getDouble("balanceChange"), set.getString("description")));
+			}
+			return events;
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	private static void saveAccountEvents(String accountNumber, List<AccountEvent> events) {
+		for (AccountEvent e : events)
+			try {
+				PreparedStatement ps = conn.prepareStatement(
+						"INSERT INTO Events (account, balanceChange, description) VALUES (?, ?, ?)");
+				ps.setString(1, accountNumber);
+				ps.setDouble(2, e.getBalanceChange());
+				ps.setString(3, e.getDescription());
+				ps.executeUpdate();
+			} catch (SQLException ex) {
+				ex.printStackTrace();
+			}
+	}
+
+	private static Account accountFromResultSet(ResultSet set) throws SQLException {
+		String num = set.getString("accountNumber");
+		return new Account(set.getString("firstName"), set.getString("lastName"), num, getAccountEvents(num));
+	}
+
+	public static List<Account> readAccounts() {
+		List<Account> accounts = new ArrayList<Account>();
+		try {
+			stmt = conn.createStatement();
+			stmt.executeQuery("SELECT * FROM Accounts");
+			ResultSet set = stmt.getResultSet();
+			while (set.next()) {
+				accounts.add(accountFromResultSet(set));
+			}
+
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		return accounts;
+	}
+
+	public static boolean inited() {
+		return conn != null;
+	}
 }

+ 24 - 8
src/eu/tankernn/accounts/frame/menu/MainMenuBar.java

@@ -13,6 +13,7 @@ import javax.swing.KeyStroke;
 
 import eu.tankernn.accounts.Account;
 import eu.tankernn.accounts.AccountManager;
+import eu.tankernn.accounts.DBManager;
 import eu.tankernn.accounts.frame.MainFrame;
 import eu.tankernn.accounts.frame.NewAccountDialog;
 
@@ -22,24 +23,28 @@ public class MainMenuBar extends JMenuBar implements ActionListener {
 	 * 
 	 */
 	private static final long serialVersionUID = 8702523319236773512L;
-	
+
 	private MainFrame frame;
-	
+
 	// Menu Items
 
 	private JMenu fileMenu = new JMenu("File");
 	private JMenuItem newFile = new JMenuItem("New..."), openFile = new JMenuItem("Open..."),
 			saveFile = new JMenuItem("Save"), saveFileAs = new JMenuItem("Save As...");
 
+	private JMenu database = new JMenu("Database");
+	private JMenuItem importDatabase = new JMenuItem("Import from database"),
+			exportDatabase = new JMenuItem("Export to database");
+
 	private JMenu accountMenu = new JMenu("Accounts");
 	private JMenuItem newAccount = new JMenuItem("New account..."), refresh = new JMenuItem("Refresh accounts");
-	
+
 	private JMenu optionsMenu = new JMenu("Options");
 	private JCheckBoxMenuItem useEncryption = new JCheckBoxMenuItem("Use encryption when saving files");
-	
+
 	public MainMenuBar(MainFrame frame) {
 		this.frame = frame;
-		
+
 		// File menu
 		addMenuWithItems(fileMenu, newFile, openFile, saveFile, saveFileAs);
 
@@ -48,9 +53,12 @@ public class MainMenuBar extends JMenuBar implements ActionListener {
 		saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK));
 		saveFileAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK | Event.SHIFT_MASK));
 
+		// Database menu
+		addMenuWithItems(database, importDatabase, exportDatabase);
+
 		// Accounts menu
 		addMenuWithItems(accountMenu, newAccount, refresh);
-		
+
 		// Options menu
 		addMenuWithItems(optionsMenu, useEncryption);
 		useEncryption.setSelected(AccountManager.isSavingWithEncryption());
@@ -77,11 +85,19 @@ public class MainMenuBar extends JMenuBar implements ActionListener {
 			AccountManager.saveFile(false);
 		} else if (src.equals(saveFileAs)) {
 			AccountManager.saveFile(true);
+		} else if (src.equals(importDatabase)) {
+			if (AccountManager.closeFile()) {
+				DBManager.init();
+				for (Account a : DBManager.readAccounts())
+					AccountManager.addAccount(a);
+			}
+		} else if (src.equals(exportDatabase)) {
+			DBManager.init();
+			DBManager.saveAccounts(AccountManager.getAccounts());
 		} else if (src.equals(newAccount)) {
 			NewAccountDialog dialog = new NewAccountDialog();
 			if (dialog.validate()) {
-				AccountManager
-						.addAccount(new Account(dialog.getFirstName(), dialog.getLastName()));
+				AccountManager.addAccount(new Account(dialog.getFirstName(), dialog.getLastName()));
 			}
 		} else if (src.equals(refresh)) {
 			frame.refresh();