Archief - [Java] MySQL aanspreken met Java via Connecter/J

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Fraggie

Legacy Member
Ik ben aan het uitzoeken wat je juist allemaal kan doen met Java & MySQL.
Alles gaat goed:
Eerst de driver loaden & vervolgens een connectie maken:

Class.forName("com.mysql.jdbc.Driver").newInstance();
db = DriverManager.getConnection("jdbc:mysql://localhost/javadb", "login", "pwd");

Vervolgens een stamtement openen en de query verzenden en opvangen

Statement stmt = db.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");

Verwerk gaat ook goed, met al de methoden van ResultSet


MAAR, gezien ik alleen nog maar in PHP met een database gewerkt had, wou ik volgende methode maken in de klasse Database:

Code:
public ResultSet mysql_query(String s) throws SQLException {
  Statement stmt = db.createStatement(); // Telkens terug een connectie openen
  ResultSet rs = stmt.executeQuery(s); 	
  return rs;
 }

Wanneer ik ze echter aanspreek uit de klasse Client:
Code:
  class KnopHandler extends Database implements ActionListener  {
    public void actionPerformed( ActionEvent e ) {
...
       try { ResultSet info = mysql_query("SELECT * FROM users WHERE *");
        while ( info.next() ) {
          System.out.printf( "%s\n", info.getObject( "id" ));	
         }
        } catch (SQLException sqle) { System.out.println("SQLException: " + sqle.getMessage()); } // Zoals mysql_error
...
krijg ik volgende error: SQLException: No operations allowed after connection closed.

Ik dacht dat de ResultSet alles uit de database haalde in in het geheugen stopte? Dus dat de connectie niet open moet blijven om er bewerkingen mee uit te voeren?!

Of moet ik telkens een nieuwe statement & resultset maken als ik even in de db wil kijken?

passero

Legacy Member
Zet eens de volledige DB klasse..

Waar open je de connectie naar de DB? En waar sluit je die af?

Het is trouwens geen goed idee om een extends DB te gebruiken voor elke klasse die de DB moet aanspreken...
je moet een apparte DB laag maken waar je dan eventueel elke tabel mapt op een klasse en zo weinig mogelijk sql gebruikt buiten je datalaag.

Fraggie

Legacy Member
Het posten van Database.java heeft geen zin gezien ze vol rommel staat. Maar je hebt toch men probleem kunne oplossen.

Ik maakte een globale var Connection db; in Database.java, en ik dacht dat als ik deze 1x juist zet in de default constructor, ze altijd paraat ging zijn om te gebruiken. Ik moest ze dus gewoon her definiëren in de methode.

Voor de rest weet ik niet wat je bedoelt mlet een db laag & tabel mappen op een klasse?

passero

Legacy Member
Stel even volgend simpel voorbeeld:
Code:
for(int i=0;i<eenArray.size;i++)
{
  try { ResultSet info = mysql_query("SELECT * FROM users WHERE user = " + eenArray[i]);
//doeIets
}
}

Als de array 10 elementjes bevat ga je 10 keer een connectie openen/sluiten wat niet bepaald goed is.

Wat het mappen betreft... zoek eens beetje info over MVC op.
Je hebt eigenlijk 3 lagen in je programma:
1) Model (het model van uw database waar elke tabel een klasse krijgt. Koppeltabellen niet natuurlijk.)
2) View: hier komen al je klasse ivm de interface. De view is normaal waar de gebruiker mee werkt. Hier zou je in princiepe NIETS van sql mogen insteken.
3) Controller. Soms wordt view en controller tot 1 laag gebracht maar je neemt ze toch best appart. Controller is de link tussen model en view en kan bijvoorbeeld validatie bevatten, omovrmen van data,...

Een voorbeeldje van een klasse die je in je model zou moeten nemen:

Code:
public class User 
{
   private int id;
   private String naam,voornaam;  

   publuc User(int id)
   {
     this.id = id;
     this.load();
    }

   public void load()
  {
     ResultSet info = DB.mysql_query("SELECT * FROM users WHERE id =" + this.id);
     this.naam = info["naam'];
     this.voornaam = info["voornaam"];
  }

  public String getNaam(){return this.naam;)
  public String getNaam(){return this.id;)
  public void setNaam(String naam){this.naam = naam;}

  public void update
  {
    DB.execute('update users set naam = "' + this.naam + "' where id = " + id);
  }
}

Op die manier kan je in je view de klasse gebruiken:

Code:
User gebruiker = new User(id);
System.out.printf(gebruiker.getNaam());
gebruiker.setNaam("eenNaam");
gebruiker.update();

Is veel duidelijker en zo blijft alles mooi samen...

De java syntax is mss niet altijd correct maar je begrijpt wel wat ik bedoel hoop ik...

forloRn_

Legacy Member
Ik zou die SQL statements ook in een aparte DAO-klasse stoppen met daarin tenminste de CRUD-operaties (Create, Read, Update, Delete), genre:
Code:
public interface UserDao {
    void insertUser(User user);
    User getUser(long id);
    int updateUser(User user);
    int deleteUser(User user);
}

Single responsibility is een mooi principe.

passero

Legacy Member
je kan in princiepe een mooie abstracte klasse schrijven hiervoor in den aard van volgende klasse:

Code:
public abstract class DAO
{
    private String[] fields;
    private String[] fieldNames;
    private String[] updatedFields; 
    private int id;

    private String tableName; 

    protected void setTable(String table){this.tableName = table;}
   public String getValue(String fieldName)
   {
      if(updatedValues[fieldname] != null) 
         return updatedValues[fieldname];
     else
         return values[fieldname];
   } 

   protected void load()
   {
        String sql = 'select * from ' + this.tableName + ' where id = ' + this.id;
        Resultset rs = DB.execute(sql);
        //loopje in de fields array op te vullen en de fieldNames op te vullen
    } 
   public function update()
   {
       
    }
   
    //getter en setter voor de ID
}

Bij de update ga je dan gewoon doorheen je array en maak je je update dynamisch. Dit kan identiek voor een insert, delete,..

Nu ipv een gewone array kan je ook collection gaan gebruiken aangezien je met een mapping zit van namen en values. Ik gebruik in mijn voorbeeld een associatieve array maar weet niet 100% zeker of die in java werkt... vandaar dat je dus eventueel een collection zal moeten gebruiken.

Als je dan een specifiek DAO object maak krijg je dit:

Code:
public class User extends DAO
{
   public User(id)
   {
      this.setId(id);
      this.load();
    }

    public function getNaam(){return this.getValue("naam");}
    public function setNaam(String naam){return this.setValue("naam",naam);}
}

Zo wordt het nog eenvoudiger. Je kan dan ook eventueel adhv factory pattern een klasse gaan schrijven waarmee je je type van DB definieert en dan een juist DAO object teruggeeft voor die DB... maar dit gaat misschien een beetje te ver ;)

Fraggie

Legacy Member
Het gaat mijn niveau te boven, maar ik zal het bekijken. Bedankt voor de extra uitleg!

Emerxill

Legacy Member
Het probleem is dat jdbc specificatie niet toelaat dat ge ResultSet doorgeeft, omdat dat niet heel verstandig is. Dan zal de connectie gesloten worden.
Het is de bedoeling dat ge de data die ge nodig hebt, uit de resultset haalt en dat doorgeeft.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan