package app.model;
//# Jon: Jeg mener fremdeles at denne klassen er en kontrollerklasse og hører
//       hjemme i pakken app.controller. :-)

import java.sql.*;

/**
 * DatabaseTilkobling.java
 *
 * Tilkobling til databasen.
 * Har brukt lokal database på macen.
 *
 * Tabellen min i databasen bruker autoinkrement for oppretting av lånenr
 * Et lånenr kan aldri gjenbrukes. Dvs. hvis det slettes, så slettes det
 * ingen ta over dette nummeret senere.
//# Jon: Det er ok. Som regel er det slik man gjør det i databaser. Dvs.
//       "ledige" primærnøkler gjenbrukes ikke.
 *
 * @author Hilde Vestøl (106288)
 * @version 0.9
 */

public class DatabaseTilkobling {

    private static final String dbDriver = "org.apache.derby.jdbc.ClientDriver";
    private static final String URL = "jdbc:derby://localhost:1527/laneapp;user=app;password=app";
    
    private static Connection forbindelse = null;
    
    /**
     *
     */

    public DatabaseTilkobling() {
    }
    
    /**
     * Etablerer databaseforbindelsen
     * @return true/false
     */

    public static boolean openDB() {
        try {
            Class.forName(dbDriver);
            forbindelse = DriverManager.getConnection(URL);
            if (forbindelse != null) {
                return true;
            } else {
                System.out.println("openDB(): Fikk ikke etablert forbindelse");
                return false;
            }
        } catch (ClassNotFoundException cnfe) {
            System.out.println("openDB(): Klarte ikke å laste JDBC driver. " + cnfe);
            return false;
        } catch (SQLException sqle) {
            System.out.println("openDB(): Klarte ikke å åpne databasen: " + sqle);
            return false;
        }
    } // end openDB()
    
    
 
    /**
     * Lagrer lånet i databasen.
     * Hvis ikke lånet finnes, skal det settes inn i databasen,
     * hvis det finnes, skal det oppdateres.
     *
     * @param lån
     * @return Loan lån
     * @throws SQLException
     * @throws LoanException
     */

    public static Loan saveToDB( Loan lån ) throws SQLException, LoanException {
    //# Jon: Jeg tror jeg ville ha valgt å behandle unntakene i denne metoden...

        
        //#Jon: if og else grenene nedenfor inneholder mange identiske kodelinjer.
        //      Se om du kan "refaktorere" slik at du blir kvitt noen av dem. :-)
        if ( lån.getLåneNR() != 0 ) {
            //# Jon: Ok å sjekke at lånenr !=0, men dette gir deg strengt tatt
            //       ingen garanti for at lånet finnes i databasen. Hvis ikke vil
            //       UPDATE setningen ikke gjøre noe. Du bør altså sjekke med en
            //       SELECT om lånenummeret finnes i basen.
            
            String sqlSetning = "UPDATE LAAN2 SET LOAN_AMOUNT = ?, LOAN_TIME = ?, LOAN_TERMIN = ?, LOAN_RENTE = ?, LOAN_TYPE = ? WHERE ID = ?";
            //# Jon: PreparedStatement er unødvendig tungvidt her og gir heller ingen gevinst her.  
            //       Det bruker vi bare når vi skal kjøre mange "like" SQL setninger etterhverandre for å unngå
            //       at DBMSet optimaliserer spørringen hver gang. I dette tilfellet oppnår du ikke det siden
            //       du kun gjør èn UPDATE for hvert PreparedStatement.
            PreparedStatement setning = forbindelse.prepareStatement(sqlSetning);
            setning.setInt(1, lån.getLånebeløp());      //Beløp
            setning.setInt(2, lån.getLøpetid());        //Løpetid
            setning.setInt(3, lån.getÅrligeTerminer()); //Termin
            setning.setDouble(4, lån.getRentesats());   //Rente
            setning.setInt(5, lån.getLånetype());       //Type lån
            setning.setInt(6, lån.getLåneNR());
            setning.executeUpdate();
            //# Jon: Du bør alltid sjekke returverdien fra executeUpdate() for å være sikker på
            //       at den faktisk oppdaterte det antall rader du forventet.
            //       Dessuten bør setning helst lukkes etter bruk.
            return lån;
            
        } else {
            String sqlSetning = "INSERT INTO LAAN2 (LOAN_AMOUNT, LOAN_TIME, LOAN_TERMIN, LOAN_RENTE, LOAN_TYPE) VALUES (?, ?, ?, ?, ?)";
            PreparedStatement setning = forbindelse.prepareStatement(sqlSetning);
            setning.setInt(1, lån.getLånebeløp());      //Beløp
            setning.setInt(2, lån.getLøpetid());        //Løpetid
            setning.setInt(3, lån.getÅrligeTerminer()); //Termin
            setning.setDouble(4, lån.getRentesats());   //Rente
            setning.setInt(5, lån.getLånetype());       //Type lån
            setning.executeUpdate();
            //# Jon: Du bør alltid sjekke returverdien fra executeUpdate() for å være sikker på
            //       at den faktisk oppdaterte det antall rader du forventet.
            //       Dessuten bør setning helst lukkes etter bruk.
            
            //#Jon: Bra at du har funnet ut hvordan du får tak i den automatisk genererte IDen!
            Statement stm = forbindelse.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            stm.setMaxRows(1);
            ResultSet res = stm.executeQuery("SELECT ID FROM LAAN2 ORDER BY ID DESC");
            if (res.next() )
            {
                lån.setLåneNr(res.getInt("ID") );
            }
            return lån;
        }
    }
    
    /**
     * Finner et lån fra databasen.
     *
     * @param låneNr
     * @param lån
     * @return
     * @throws SQLException
     * @throws LoanException
     */

    public static Loan findFromDB(int låneNr, Loan lån) throws SQLException, LoanException {
        //#Jon: Du behøver vel ikke lån som parameter her så lenge metoden skal returnere
        //      lånet som er funnet? Du kan vel bare bygget et nytt Loan objekt?
        Statement stm = forbindelse.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        stm.setMaxRows(1);
        ResultSet res = stm.executeQuery("SELECT * FROM LAAN2 WHERE ID =" + låneNr);
        if (res.next() ){
            lån.setLåneNr(res.getInt("ID") );
            lån.setLånebeløp(res.getInt("LOAN_AMOUNT") );
            lån.setLøpetid(res.getInt("LOAN_TIME"));
            lån.setÅrligeTerminer(res.getInt ("LOAN_TERMIN"));
            lån.setRentesats(res.getDouble("LOAN_RENTE"));
            lån.setLånetype(res.getInt("LOAN_TYPE"));
            return lån;
        } else {
            throw new LoanException("Fant ikke låneID");
        }
    }
    
    /**
     * Sletter et lån med gitt lånenr fra databasen.
     * @param låneNr
     * @return
     * @throws SQLException
     */

    public static boolean deleteFromDB(int låneNr) throws SQLException {
        String sql = "DELETE FROM LAAN2 WHERE ID = " + låneNr;
        PreparedStatement setning = forbindelse.prepareStatement(sql);
        setning.execute();
        if (setning.getUpdateCount() > 0)
            return true;
        throw new SQLException();
    }
    
  
    /**
     * Lukker databaseforbindelsen
     * @return boolean
     */

    public static boolean closeDB() {
        try {
            forbindelse.close();
            return true;
        } catch (SQLException sqle) {
            System.out.println("closeDB(): Klarte ikke å lukke databasen. " + sqle);
            return false;
        }
    }

}

Kontaktinfo

Hilde Vestøl
98883064
hilde@vestol.net

kart