Avatar billede Droa Seniormester
12. december 2012 - 00:24 Der er 9 kommentarer og
1 løsning

Database klasse, til at gøre mysql tilgang lettere.

Jeg har lavet et lille stykke kode, for at gøre tilgang til en mySQL database lettere, jeg ville bare høre om det jeg har lavet ville være i stand til at virke, uden jeg ville få alt for store problemer, da jeg gerne vil bruge det i sammenhæng med en java socket server.

hvor godt ville denne kode virke? det er mit første forsøg, da jeg ikke rigtigt har lavet alt for meget af den type kodning før.

Database class

package dk.minsk.util.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class Database {
    Connection con = null;
   
    public Database(String server, int port, String database,String user, String password) throws SQLException, ClassNotFoundException{
        String url = "jdbc:mysql://"+server+":"+port+"/"+database;
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection(url, user, password);
    }
   
    public Database(String server, String database, String user, String password) throws SQLException, ClassNotFoundException {
        this(server, 3306, database, user, password);
    }
   
    public List<DataRow> Query(String sql){
        try {
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(sql);
            ResultSetMetaData rsmd = rs.getMetaData();
           
            List<DataRow> rrs = new ArrayList<DataRow>();
           
            while(rs.next()){
                DataRow dt = new DataRow();
                for(int i = 1;i<=rsmd.getColumnCount();i++){
                    dt.addEntity(i, rsmd.getColumnName(i), rs.getObject(i));
                }
                rrs.add(dt);
            }
           
            rs.close();
            st.close();
            return rrs;
        } catch (SQLException e) {
            return null;
        }
    }
   
    public boolean Execute(String sql){
        try {
            Statement st = con.createStatement();
            Boolean rs = st.execute(sql);
            return rs;
        } catch (SQLException e) {
            return false;
        }
    }
   
    public boolean close(){
        try {
            con.close();
            return true;
        } catch (SQLException e) {
            return false;
        }
    }
}


DataRow class

package dk.minsk.util.db;

import java.util.HashMap;
import java.util.Map;

public class DataRow {
    //Gemmer Data, og kolonne navn
    private Map<String,Object> map = new HashMap<String,Object>();
   
    //Gemmer Kolonner og deres relative position "1, id" "2, bruger" "3, password"
    private Map<Integer,String> columns = new HashMap<Integer,String>();
   
    public Object getColumnValue(int i){
        //bruger Overloaded getColumnValue(String name), efter at have fundet det korrekte navn for den column den skal hente fra
        return getColumnValue(getColumnIndexName(i));
    }
   
    public void addEntity(int index, String column, Object item){
        this.columns.put(index, column);
        this.map.put(column, item);
    }
   
    public Object getColumnValue(String name){
        //retunere værdien af map hvor nøglen er navnet man spørger efter
        return this.map.get(name);
    }
   
    public String getColumnIndexName(int i){
        //Giver navngivningen af indexes for denne Tabelrække
        return this.columns.get(i);
    }
   
//    public Map<Integer,String> getColumnNames(){
//        //Kontaktled til columns
//        return this.columns;
//    }
   
//    public Map<String,Object> getMap() {
//        //kontaktled til værdierne
//        return this.map;
//    }
}


Test af klasser

import java.sql.SQLException;
import java.util.List;
import dk.minsk.util.db.DataRow;
import dk.minsk.util.db.Database;


public class Test {

    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Database db = new Database("localhost", "testdb", "testuser", "testpassword");
        List<DataRow> users = db.Query("SELECT * FROM testtable");
       
        for(DataRow user : users){
            System.out.println(user.getColumnIndexName(4)+": "+user.getColumnValue(4));
        }
        db.close();
    }

}
Avatar billede arne_v Ekspert
12. december 2012 - 00:37 #1
Umiddelbart ser koden rimelig OK ud.

Muligheder for forbedring:

* du skal have skiftet fra Statement til PreparedStatement

* du boer se om du kan hente kolonne navne en enkelt gang fremfor for hver raekke

* hvis du kun skal understoette ny Java (1.7+) saa kan du overveje den nye maade at faa closed resourcer paa

* du kan overveje om du fremfor en permanent open connection skulle bruge en connection pool og open/close for hver operation

* brug 5 minutter paa at checke *RowSet og se om du kunne bruge noget derfra
Avatar billede Droa Seniormester
12. december 2012 - 01:10 #2
mange tak, jeg læste lige om PreparedStatement, og det virker os som det mest logiske at bruge, så man ikke stresser sql serveren mere end nødvendigt.
det med kolonne navnene har jeg tænkt meget over, og er lidt derude hvor jeg tænker jeg nok bliver nød til at lave en yderligere class,, muligvis en extension af mit ArrayList, for at kunne gemme informationen derude istedet for i hver række.
Det der du snakker om med 1.7 er det AutoCloseable?
eksempel jeg fandt...

try (InputStream is = new FileInputStream(file)) {
}catch (FileNotFoundException ex) { 
  System.err.println("Missing file " + file.getAbsolutePath()); 
}


Den ide med en connection pool, har jeg tænkt meget på at bruge, da jeg skal bruge den på en serverside som login, jeg har prøvet at lave Database mulig at udvide med en Threaded Connection Pool forbindelse, så jeg kan have en bedre tilgang, det er lidt grunden til jeg har prøvet at lave det hele så simpelt som muligt.
Jeg kiggede lidt på RowSet, og har ikke helt set alle pros og cons med den, ud over det er lidt det samme som ResultSet, men at den os virker efter forbindelsen lukker.
Grunden til jeg selv lavede TableRow classen, var fordi jeg ikke kender så meget til syncronized data, og prøver at holde mig til data tabel-lagre jeg kender til, hvis jeg nu vælger at udvide til Threaded forbindelser.

Men jeg vil helt bestemt prøve at se om det ville virke bedre, da jeg godt kan se fordelen i at bruge den :)

Tak for alle de gode punkter.. ligger du et svar?
Avatar billede arne_v Ekspert
12. december 2012 - 01:55 #3
Maaske skal du have en DataResult klasse som har en List<DataRow> og saa kan du gemme navnene paa DataResult niveau.

Det er det du foreslaar bare med encapsulation fremfor inheritance.
Avatar billede arne_v Ekspert
12. december 2012 - 01:56 #4
Ja. AutoCloseable.
Avatar billede arne_v Ekspert
12. december 2012 - 01:57 #5
Hvis du koerer i en Java EE kontekst, saa er der en connection pool til raadighed,

Hvis du koerer ren Java SE (en standalone socket server er ren Java SE), saa kan du f.eks. bruge Apache connection pool. Ingen grund til selv at opfinde noget.
Avatar billede arne_v Ekspert
12. december 2012 - 01:58 #6
Du kan ogsaa overveje om du skal et abstraktions niveau op og erstatte direkte JDBC med ORM.
Avatar billede arne_v Ekspert
12. december 2012 - 01:58 #7
og et svar
Avatar billede Droa Seniormester
12. december 2012 - 10:24 #8
tak igen for alle de mange gode råd, det er bestemt forbedringer jeg vil tage op og implementere :)
Avatar billede Droa Seniormester
13. december 2012 - 21:42 #9
ligger lige denne her, omkring Apache Connection Pools
http://www.java2s.com/Code/Java/Apache-Common/Connection-Pool.htm
Avatar billede arne_v Ekspert
14. december 2012 - 02:42 #10
Jeg har ogsaa et eksempel paa lager:

        Class.forName("com.mysql.jdbc.Driver");
        GenericObjectPool cp = new GenericObjectPool(null);
        DriverManagerConnectionFactory dmcf = new DriverManagerConnectionFactory("jdbc:mysql://localhost/Test", "", "");
        PoolableConnectionFactory pcf = new PoolableConnectionFactory(dmcf, cp, null, null, false, true);
        PoolingDataSource ds = new PoolingDataSource(cp);
        Connection con = ds.getConnection();
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester