[ erno @ 20.03.2007. 13:18 ] @
koristite li mozda neki gotov connection handler za database? posto pisem neku aplikaciju u JSP koja koristi mysql bazu podataka zanima me na koji nacin vi rjesavate problem prenosenja objekta konekcije sa jedne stranice na drugu. kod php-a ovo nisam morao raditi jednom se konektujem i to je to. mozda da, nakon svakog izvrsenog query-a zatvorim konekciju ili ima neko bolje rjesenje. u ovom slucaju mi nije performansa vazna (konekcije/diskonekcije), ali ako mogu koristiti neku bolju soluciju zasto ne.
[ rj444 @ 20.03.2007. 13:22 ] @
Ja napravim svoju klasu DBKernel, koja ima interfejs za izvrsavanje upita, konekciju, diskonelciju na bazu, itd.
Realizujem je kao Singleton uzorak (postoji samo jedna instanca klase u svakom trenutku), tako da objekat kernela dobijas preko staticke metode, sto te oslobadja potrebe za eksplicitnim prenosenjem objekta. Konekciju ne zatvaras svaki put vec samo kada je tebi to potrebno.

Evo kostura te klase:

Code:
public class DBKernel {
    private static DBKernel instance = null;
    //privatan da ne bi se kontrolisalo kreiranje instanci
    private DBKernel() {
        //kreiras konekciju ka bazi
    }
    //ako konekcije nema, kreiraj je i vrati instancu. inace samo vrati postojecu konekciju
    public static DBKernel getInstance() {
        if (instance==null) instance=new DBKernel();
        return instance;
    }
    ...
    //dalje stavis metode koje ti trebaju
    public void executeQuery(String query) { ... }
    ...
}


[Ovu poruku je menjao rj444 dana 20.03.2007. u 14:48 GMT+1]
[ erno @ 20.03.2007. 13:27 ] @
ja sam svoju klasu napravio kao singleton ali nisam siguran dal svaki put vraca istu instancu. ako treba postat cu code. imam sljedecu situaciju: imam jedan main prozor iz kojeg otvorim novi prozor (oba moraju pristupiti bazi - glavni mi prikaze sve recorde u bazi, a novi mi daje mogucnost da recimo dodam novi record ili brisem postojeci). sad nisam siguran dal imam jednu ili dvije instance MySQL objekta, odnosno, dal imam na MySQL serveru otvorenu jednu ili dvije konekcije. thnx za brz odgovor ;-)

poz
[ rj444 @ 20.03.2007. 14:17 ] @
Ako si to realizovao kao singleton, onda imas jednu konekciju sigurno jer se ona kreira u konstruktoru one gore klase DBKernel.
Medjutim, ta konekcija moze da ima vise konkurentnih niti ili cega vec, sto zavisi od drajvera za bazu koji koristis (JDBC konektor ili JDBC-ODBC most ...).
Sve to tebe ne zanima, jer to kontrolise taj drajver. Ono sto ti mozes da kotrolises je broj uspostavljanja konekcija sa bazom, sto je najsporije. Ovako kako si ti to napravio, konekcija se uspostavlja jednom i cuva se dalje.

Ako te zanima koliko imas konekcija u MySQL-u, to mozes videti iz MySQL Admin-a.
[ erno @ 20.03.2007. 14:39 ] @
ok to me je i zanimalo. dakle kad prvi put stvorim svoj objekt, nema veze iz kog prozora pozovem metod MySQL.getInstance() (kod mene), bice vracena ta instanca. thnx a lot majstore ;-)
[ rj444 @ 20.03.2007. 23:32 ] @
Naravno jer ko prvi pozove getInstance() on ce da kreira instancu i da je dobije nazad, svi ostali ce samo da je dobijaju nazad. To je poenta Singleton uzorka.
[ erno @ 21.03.2007. 11:04 ] @
ok. thnx za odgovore ;-). sad imam jedan drugi problem. ne mogu izvrsiti vise upita jedan za drugim. npr. ne mogu izvrsiti sljedeca dva query-a:

MySQL.getInstance().executeQuery("SELECT * FROM tbl_students");
...
MySQL.getInstance().executeQuery("SELECT * FROM tbl_courses_students WHERE student_id=" + id);

primjer je bezze al nesto slicno tome.

kad izvrsavam jedan query sve je super kad pokusam izvrsiti oba dobijem sljedece kao rezultat:

java.lang.NullPointerException
com.mysql.jdbc.ResultSet.findColumn(ResultSet.java:934)
com.mysql.jdbc.ResultSet.getString(ResultSet.java:5436)
presentation.DisplayOperation.getStudentsTable(DisplayOperation.java:90)
org.apache.jsp.index_jsp._jspService(index_jsp.java:159)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:322)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:291)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

pokusao sam svaki puta kad pokrenem executeQuery moj property statement (tip Statement) ponovo inicijalizovati a na kraju zatvoriti ali onda ne dobijem nista.
moja executeQuery metoda bi ovako izgledala (trenutno i ova verzija radi onako kako sam naveo gore):

Code:


public ResultSet executeQuery(String query) {
  ResultSet result = null;
  try {
    result = statement.executeQuery(query);
  } catch (SQLException e) {
    System.out.println(e.getMessage());
  }
  
  return result;
}



statement mi je inicijalizovan u connect metodi, dakle kad se konektujem modmah i napravim novi statement. vjerovatno je tu greska pa vas molim ako mi mozete ovo malo pojasniti. thnx

poz
[ anon315 @ 21.03.2007. 11:18 ] @
Baci nam liniju 90 od DisplayOperation.java i njenu okolinu
[ erno @ 21.03.2007. 11:28 ] @
u principu je to metoda koja mi samo vraca tabelu sa podacima koji se nalaze u ResultSet-u. Trenutno ide tako da prolazim i dodajem sve studente u tu svoju pomocnu varijablu (String) sto radi normalno. problem nastaje kad zelim i da provjerim kojem (bubam bezze) smjeru pripada student satim id-om tj. kad hocu da izvrsim jos jedan query. s obzirom da metoda normalno vrati html (bez ovog drugog query-a) nema ni potrebe da mislim da je kod nje problem. problem moze biti samo u mojoj implementaciji za MySQL klasu. Ako treba postat cu tu klasu ovdje. Siguran sam da problem nije sa ovom metodom jer mi baca isti exception gdje god pokusam jos jedan query izvrsiti. thnx
[ anon315 @ 21.03.2007. 11:34 ] @
Ok, ali vidim da si tu dobio null pointer, sto je dobra tacka da se krene sa debagovanjem..
[ erno @ 21.03.2007. 12:29 ] @
ok evo testni primjer (doduse sad ne baca exception):

Code:


public static String getStudentsTable() {
        String html = "1"; // udje
        
        if(MySQL.getInstance().isConnected()) {
            ResultSet result = MySQL.getInstance().executeQuery("SELECT * FROM tbl_students");
            ResultSet result2 = null;
            int studentId        = 0;
            int studyId     = 0;
            String studyTitle  = null;
            
            try {
                html = "2"; // udje
                
                int numberOfRecords = MySQL.getInstance().getNumberOfRecords(result);
                
                while(result.next()) {
                    html = "3"; // udje i ovo ce mi biti vraceno
                    studentId = Integer.parseInt(result.getString("student_id"));
                    studyId = Integer.parseInt(result.getString("study_id"));
                    result2 = MySQL.getInstance().executeQuery("SELECT * FROM tbl_studies_students WHERE study_id = " 
                            + studyId);
                    studyTitle = result2.getString("title"); // tu stane
                    html = studyTitle; // pokusavam ispisati naziv smjera studenta
                }
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        
        return html;
    }



[Ovu poruku je menjao erno dana 21.03.2007. u 13:54 GMT+1]
[ Toxter @ 21.03.2007. 13:08 ] @
Zasto radis ovo:
Citat:
erno:
Code:

studentId = Integer.parseInt(result.getString("student_id"));



Kad mozes lepo da izvuces int:
Code:
studentId = result.getInt("student_id");


???


a greska ti je ovde:
Code:
result2 = MySQL.getInstance().executeQuery("SELECT * FROM tbl_studies_students WHERE study_id = " 
                            + studyId);
studyTitle = result2.getString("title"); // tu stane


treba da "dohvatis" prvi row u ResultSetu pa zato posle ove executeQuery() metode moras uraditi i ovo:
Code:
result2.next();
[ erno @ 21.03.2007. 13:10 ] @
hvala. nije li efekt isti?

sto se tice result2.next(); - to sam zaboravio tu napisati ali imam u code-u taj dio ;-)

poz
[ erno @ 22.03.2007. 12:57 ] @
ne vidim stvarno sta bi mogla biti greska osim to da koristim isti statement za oba query-a. evo i code od mysql classe:

Code:


public final class MySQL extends DBConnection implements IDatabase {

    private String database     = null;

    private Statement statement = null;

    private static MySQL singleton = null;
    
    private MySQL() {
        
    }
    
    public static MySQL getInstance() {
        if(singleton == null) {
            singleton = new MySQL();
            singleton.init();
            singleton.setHostname("****");
            singleton.setUsername("****");
            singleton.setPassword("****");
            singleton.setDatabase("****");
            singleton.connect();
        }
        
        return singleton;
    }
    
    private void init() {
        // initialize mysql driver
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            //connected = true;
            //System.out.println("Database driver initialization - ok");
        } catch (Exception e) {
            //System.out.println("Database driver initialization - error");
        }
    }
    
    public boolean connect() {
        boolean status = false;
        
        // try to connect to database
        try {
            connection = DriverManager.getConnection("jdbc:mysql://" + hostname 
                    + "/" + database + "?user=" + username + "&password=" + password);
            if(connection != null) {
                status = true;
                connected = true;
            }
            statement = connection.createStatement();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        return status;
    }
    
    public void disconnect() {
        // close connection to MySQL server
        try {
            connected = false;
            connection.close();
            statement.close();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    
    public ResultSet executeQuery(String query) {
        ResultSet result = null;
        
        // running query and getting result
        try {
            result = statement.executeQuery(query);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        return result;
    }
    
    public int executeUpdate(String query) {
        int result = 0;
        // running query and getting result
        try {
            result = statement.executeUpdate(query);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        return result;
    }

    public int getNumberOfRecords(ResultSet result) {
        int counter = 0;
        
        try {
            while(result.next()) {
                counter++;
            }
            
            result.beforeFirst();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        return counter;
    }

}



dakle, mora li moja executeQuery metoda kad god pozovem imati svoj statement ili mogu sa jednim statementom vise querys izvrsiti. thnx

poz
[ Toxter @ 22.03.2007. 13:24 ] @
Citat:
erno:
dakle, mora li moja executeQuery metoda kad god pozovem imati svoj statement ili mogu sa jednim statementom vise querys izvrsiti. thnx


Da tu ti je problem.
U sustini treba da napravis samo ConnectionPool klasu a ostalo (Statement, ResultSet) kreiras
u kodu. Za svaki SQL query napravi poseban statement.
Evo procitaj opis interfejsa Statement , odnosno
dovoljno ti je da procitas prvu recenicu na stranici.

Takodje pogledaj PreparedStatement
[ erno @ 22.03.2007. 13:34 ] @
ok to je vec nesto hvala ti puno ;-). sad radi sve kako treba.

poz,
erno

[Ovu poruku je menjao erno dana 23.03.2007. u 10:00 GMT+1]
[ mvasicdo @ 18.04.2007. 12:44 ] @
Pozdrav, da se nadovezem na pitanje, kada sam napravio klasu npr. MySQL, na koji nacin je pozivam iz JSP stranice tj. kako je importujem itd. Koristim Eclipse i JBoss server, mozete li mi objasniti ...