Data access objects

di il
2 risposte

Data access objects

Ciao a tutti,
Io sto facendo un'applicazione web in cui l'utente dovrebbe loggarsi, poter visualizzare i propri conti e visualizzarne tutti i dettagli. Potrebbe anche effettuare un trasferimento di denaro verso un conto destinatario. ho fatto quindi una classe UserDAO (per credenziali e dettagli utenti), una BankAccountDAO (per dettagli dei conti correnti quali saldo, codice proprietario e codice conto) e una TransferDAO (per data dei trasferimenti, importo trasferito, conto origine e conto destinazione). Nella BankAccountDAO ho scritto un metodo che prima fa un controllo per vedere se il conto da cui dedurre l'importo ha un saldo >= dell'importo specificato. Poi se questo metodo ritorna un valore true dovrei chiamare un metodo della TransferDAO che deduce l'importo dal conto d'origine, lo aggiunge al conto destinatario e quindi modifica i saldi di entrambi. Quello che mi chiedevo io è: è possibile usare tante query in un solo metodo? Perchè se così fosse io ci ho provato ma mi sono fermat perchè sembra venga fuori un metodo chilometrico, dovrei dichiarare un result set per ogni query e dovrei fare un blocco try-catch-finally per ogni operazione. Quindi mi chiedevo se ci fosse un modo migliore per poter fare questa cosa. (Quanto ai controlli dell' effettiva esistenza dei conti sono già fatti da un altro metodo)

idc = id conto corrente
amount = importo da dedurre
balance = saldo
recipientAccId = conto corrente destinatario
senderAccId = conto corrente mittente
bankacc = tabella conti correnti nel db
transfers = tabella trasferimenti nel db

//method that checks whether the account balance is greater than or equal to the amount (BankAccountDAO)
	public boolean availabilityCheck(int idc, float amount) throws SQLException{
		String query = "SELECT balance FROM bankacc WHERE idc = ?";
		PreparedStatement pstatement = null;
		ResultSet result = null;
		boolean check;
		try {
			pstatement = connection.prepareStatement(query);
			pstatement.setInt(1, idc);
			result = pstatement.executeQuery();
			result.next();
			if(result.getFloat("balance") >= amount) {
				check = true;
			}
			else {
				check = false;
				}
		} catch(SQLException e) {
			e.printStackTrace();
			throw new SQLException(e);
		} finally {
			try {
				result.close();
			} catch(SQLException e1) {
				throw new SQLException(e1);
			}
			try {
				pstatement.close();
			} catch(SQLException e2) {
				throw new SQLException(e2);
			}
		}
		return check;
	}
	
	//method that picks up the amount from the the sender's account and adds it to the receiver account (TransferDAO)
	public boolean transferMoney(int recipientAccId, int senderAccId, float amount) throws SQLException {
		String query = "SELECT tAmount FROM bankacc WHERE recipientAccId = ?";
		String queryx = "UPDATE bankacc SET tAmount = ? WHERE recipientAccId = ?";
		String queryxy = "SELECT tAmount FROM bankacc WHERE senderAccId = ?";
		String queryxx = "UPDATE bankacc SET tAmount = ? WHERE senderAccId = ?";
		PreparedStatement pstatement = null;
		PreparedStatement pstatementx = null;
		ResultSet result = null;
		ResultSet resultx = null;
		float updatedBalance = 0;
		boolean transferred;
		try {
			pstatement = connection.prepareStatement(query);
			pstatement.setFloat(1, recipientAccId);
			result = pstatement.executeQuery();
			result.next();
			updatedBalance = result.getFloat("tAmount") + amount;
		} catch(SQLException e) {
			e.printStackTrace();
			throw new SQLException(e);
		} finally {
			try {
				result.close();
			} catch(SQLException e1) {
				throw new SQLException(e1);
			}
			try {
				pstatement.close();
			} catch(SQLException e2) {
				throw new SQLException(e2);
			}
		}
		try {
			pstatementx = connection.prepareStatement(queryx);
			pstatementx.setFloat(1, updatedBalance);
			pstatementx.setInt(2, recipientAccId);
		}
	}

2 Risposte

  • Re: Data access objects

    DadaLilli ha scritto:


    è possibile usare tante query in un solo metodo?
    Generalmente in una classe "DAO" ciascun metodo fa solo una (1) query su DB e basta. Ma perché tipicamente si fa così ...
    Poi, sempre generalmente/tipicamente, è uno strato "superiore" (es. un "Service", nell'accezione di Spring Framework) che mette insieme più chiamate a uno o più metodi di uno o più DAO.

    E in tutto quello che hai scritto finora, presumo che non hai considerato una cosa importante. Quando si fa questa "classica" implementazione del trasferimento da un conto ad un altro, deve essere fatto tutto in maniera "transazionale". Ovvero come si dice, si deve seguire l'approccio "o tutto o niente".
    Se il update per togliere 100 euro dal conto A ha successo ma il update per aggiungere i 100 Euro al conto B fallisce, deve essere fatto un "rollback" perché il primo update deve essere annullato. Solo se entrambi gli update hanno successo allora si fa il "commit" delle modifiche su DB. Altrimenti deve apparire come se nulla sia stato fatto (appunto: o tutto o niente).

    DadaLilli ha scritto:


    Perchè se così fosse io ci ho provato ma mi sono fermat perchè sembra venga fuori un metodo chilometrico, dovrei dichiarare un result set per ogni query e dovrei fare un blocco try-catch-finally per ogni operazione. Quindi mi chiedevo se ci fosse un modo migliore per poter fare questa cosa.
    Certo che si può fare di meglio: se l'applicazione ha tante query, può aver senso usare/realizzare uno "strato" apposito per nascondere tutta la parte "intricata" e ripetitiva di JDBC. Ovvero si realizza quello che si definisce un "template", uno scheletro di codice che gestisce il flusso generale per fare la query con JDBC che sostanzialmente rappresenta tutto ciò che NON cambia da una query all'altra. E poi si rende parametrabile/configurabile ciò che invece cambia da una query all'altra.

    Quando si usa Spring Framework ad esempio si possono usare i JDBC template di Spring. Se nella tua applicazione stai usando JDBC "da zero" senza l'uso di librerie/framework particolari, ovviamente non c'è nulla di già fatto in questo senso dei template. Ma un sistema di "template" anche basilare/minimale lo si può realizzare. Per farlo serve avere buone basi sulla OOP e possono essere utili le interfacce e la conoscenza dei design pattern in generale. E anche la conoscenza dei generics risulta utile, specialmente per la parte di mappatura del ResultSet, al fine di fare una logica che sia generica e riutilizzabile.
    E se si può usare almeno Java 8, allora tutte le belle novità, functional interfaces, lambda expression, method references, ecc... diventano anche questi moooolto utili!
  • Re: Data access objects

    Grazie mille per la risposta e le informazioni!!
Devi accedere o registrarti per scrivere nel forum
2 risposte