我对此做了一些修改:
我所做的改变是:
对于如何在我的MainApplication类中处理/调用db变量,我仍然犹豫不决。您是否认为initializeDatabaseVariables方法是可以接受的,还是更愿意继续创建一个不同的类来处理数据库连接(初始化、连接、关闭)?
下面是修改后的源代码。如果还有什么值得修改的地方,请不要犹豫,告诉我。
#Mon Jun 02 21:37:18 CEST 2014
port=3306
hostname=localhost
password=
database=jdbc_example
username=test_userpackage com.jdbcbank;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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.Properties;
import java.util.Scanner;
public class MainApplication {
// Database access
static String DB_NAME;
static String HOSTNAME;
static String DB_PORT;
static String DB_URL;
// Database credentials
static String DB_USR;
static String DB_PASS;
// Connection variables
static Connection conn = null;
static Statement statement = null;
static ResultSet result = null;
static PreparedStatement pStatement = null;
public static void main(String[] args) throws SQLException {
initializeDatabaseVariables();
int testUserId = 1;
int accountBalances[];
try {
// Connect to database
MainApplication.connectToDb();
// Get current balance
BankAccount bankAccount = new BankAccount();
accountBalances = bankAccount.getAccountBalances(testUserId);
System.out.println("---------------");
System.out.println("Current balance ");
System.out.println("---------------");
System.out.println("Checking Account: " + accountBalances[0]+ " USD");
System.out.println("Savings Account: " + accountBalances[1]+ " USD\n");
checkIfValueIsNegative(accountBalances[0]);
System.out
.print("Enter the amount (in USD) you wish to move to your savings account: ");
// Run transaction
Scanner transferAmountScanner = new Scanner(System.in);
int transferAmount = transferAmountScanner.nextInt();
transferAmountScanner.close();
checkIfValueIsOutOfRange(testUserId, transferAmount);
checkIfValueIsNegative(transferAmount);
bankAccount.moveAmountFromCheckingToSavings(transferAmount);
// Get new balance
accountBalances = bankAccount.getAccountBalances(testUserId);
System.out.println();
System.out.println("-----------");
System.out.println("New balance ");
System.out.println("-----------");
System.out.println("Checking Account: " + accountBalances[0]+ " USD");
System.out.println("Savings Account: " + accountBalances[1]+ " USD\n");
System.out.println("Thank you.");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
// Close all connections
close(conn, statement, pStatement, result);
}
}
public static void initializeDatabaseVariables() {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
// Load properties file
prop.load(input);
// Initialize database variables
DB_NAME = prop.getProperty("database");
HOSTNAME = prop.getProperty("hostname");
DB_PORT = prop.getProperty("port");
DB_USR = prop.getProperty("username");
DB_PASS = prop.getProperty("password");
DB_URL = "jdbc:mysql://" + HOSTNAME + ":" + DB_PORT + "/" + DB_NAME;
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
}
public static void checkIfValueIsNegative(int value) {
if (value < 0) {
throw new IllegalArgumentException(
"Oops! Negative values not allowed.");
}
}
public static void checkIfValueIsOutOfRange(int testUserId,
int transferAmount) throws SQLException {
int checkingBalance = new BankAccount().getAccountBalances(testUserId)[0];
if (transferAmount > checkingBalance) {
throw new IllegalArgumentException("Oops! Insuficient funds to transfer.");
}
}
public static void connectToDb() {
try {
// Load driver
Class.forName("com.mysql.jdbc.Driver");
// Set connection
conn = DriverManager.getConnection(DB_URL, DB_USR, DB_PASS);
conn.setAutoCommit(false);
statement = conn.createStatement();
} catch (ClassNotFoundException e) {
System.out.println("Error: " + e.getMessage());
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
public static void close(Connection conn, Statement statement,
PreparedStatement pStatement, ResultSet result) {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
if (statement != null)
try {
statement.close();
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
if (pStatement != null)
try {
pStatement.close();
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
if (result != null)
try {
result.close();
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
}package com.jdbcbank;
import java.sql.*;
public class BankAccount {
public void moveAmountFromCheckingToSavings(int transferAmount) throws SQLException {
try {
// Withdraw from checking and deposit into saving
withdrawFromChecking(MainApplication.statement, transferAmount, 1);
depositIntoSaving(MainApplication.statement, transferAmount, 1);
// Execute batch and commit if no issues are found
MainApplication.statement.executeBatch();
MainApplication.conn.commit();
// Print message
System.out.println("Successful transaction!");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
MainApplication.conn.rollback();
}
}
public int[] getAccountBalances(int id) throws SQLException {
// Array to be returned
int balance[] = new int[2];
// Get results
String query = "SELECT * from bank_account WHERE id = " + id;
MainApplication.result = MainApplication.statement.executeQuery(query);
while (MainApplication.result.next()) {
// Retrieve by column name
balance[0] = MainApplication.result.getInt("checking_balance");
balance[1] = MainApplication.result.getInt("saving_balance");
}
return balance;
}
public static void withdrawFromChecking(Statement statement, int amount,
int id) throws SQLException {
statement
.addBatch("UPDATE bank_account SET checking_balance = checking_balance - "
+ amount + " WHERE id = " + id);
}
public static void depositIntoSaving(Statement statement, int amount, int id)
throws SQLException {
statement
.addBatch("UPDATE bank_account SET saving_balance = saving_balance + "
+ amount + " WHERE id = " + id);
}
}发布于 2014-06-04 02:02:55
一般性建议
具体点
printlns系列提取为一种新的BankAccount.displayBalances()方法。这还将使您能够摆脱accountBalances变量。Connection一段时间,但是所有其他的都可以是本地的,范围很小。创建新的Statements或ResultSets没有任何开销,当您重用这样的变量时,bug很容易出现。new Scanner、checkIfValueIsOutOfRange和println这样的东西找到更好的地方。boolean validateMoveAmountFromCheckingToSavings(int),或者如果业务逻辑禁止,则让方法moveAmountFromCheckingToSavings抛出异常。initializeDatabaseVariables的问题:最好避免使用全局变量。也许可以创建一个Properties MainApplication.loadProperties()方法,并在main方法中保留返回的属性。更改connectToDb()以将该Properties作为参数。您甚至可能希望创建String MainApplication.createConnectionString(Properties),这是非常自我记录的。close Connection、Statement、PreparedStatement和ResultSet中的所有方法。你可能会发现你不需要关闭所有的东西。发布于 2014-06-04 07:48:48
我认为重新设计一下你的阶级等级会带来好处的。你所拥有的实体似乎:
基于此,您将创建主应用程序的一个实例和BankAccount (源和目标帐户)的两个实例。
主应用程序将创建一个数据库连接,然后为源和目标(或检查/保存任何内容)构造两个帐户(同级)。BankAccount的构造函数将把数据库连接作为参数。所以主要的应用程序需要做的就是:
好的类层次结构的一个标志是完全没有静态方法--也就是说,每个动作都对一个对象起作用。当前的设计在主应用程序中有属于BankAccount类的方法。例如,depositIntoSaving(数量)应该是savingsAccount.deposit(数量)
此外,我不喜欢检查异常(例如,SQLException)。我倾向于从源代码中捕捉到这些信息,并将它们转化为RunTimeException实例,这些实例不会在代码中出现不必要的抛出声明--但这是个人偏好,而且我可能要挑起一场宗教战争。
祝好运!
https://codereview.stackexchange.com/questions/52367
复制相似问题