Database queries in een method voor multiple usage

Status
Niet open voor verdere reacties.

Clemens Schalkw

Gebruiker
Lid geworden
5 dec 2007
Berichten
166
Ik probeer methods te schrijven die kunnen zorgen voor het ophalen van gegevens uit de database.
Opzich lukt het prima om iets uit de database te halen, maar om er een method voor te schrijven die ik dan kan hergebruiken lukt me nog even niet.

Als ik een method schrijf die simpele gegevens uit een database moet halen (niet met WHERE en zeker niet met JOIN) hoe werkt dat dan.

De volgende method staat in mijn Database.java:

Code:
      public void selectQuery(String table, String[] column) {
          try {
            statement = connection.createStatement();
            result = statement.executeQuery("SELECT" + column + " FROM " + table);
        } catch (SQLException ex) {
            System.out.println(ex.getCause());
        }
      }

Nou dacht ik eerst dat ik misschien ipv void een ResultSet moet returnen, maar ik krijg er met geen mogelijkheid data uit.

Dit staat in een andere class
Code:
    public class SaveAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            Database d = new Database();
            d.jdbcConnect();
            d.selectQuery("test", "test_id, test_name");
        }
    }



[EDIT]
Ik heb nog even verder gekeken en heb iets gevonden op javaworld.com.
Ik krijg een SQLException in main "Illigal operation on empty result set".
Het gaat fout in de method:

// Retrieve data
fieldvalues_out = acc.select( fieldnames, "test_id", (new Integer(0)) );


De hele code is:

Code:
import java.util.*;
import java.io.*;
import java.sql.*;
import java.math.*;


public class AccessMethods {

  private String DRIVER;
  private String URL;
  private String USER;
  private String PASSWD;
  private String TABLENAME;


  public AccessMethods(String driver, String url, String username,
                       String passwd, String tablename) {


    DRIVER = driver;
    URL = url;
    USER = username;
    PASSWD = passwd;
    TABLENAME = tablename;

  }

  public static void main(String args[]) throws Exception {

// I changed access information like Driver and username / password
    AccessMethods acc = new AccessMethods( "MyDriverPath",
                                           "jdbc:mysql://localhost/clemens",
                                           "username",
                                           "password",
                                           "test" );

    String [] fieldnames = { "test_id", "test_name" };

    // fieldvalues_in contains the data to put in the database
    Object [] fieldvalues_in = new Object[fieldnames.length];

    // fieldvalues_out contains the data retrieved from the database
    Object [] fieldvalues_out;


    // Make up some data
    fieldvalues_in[0] = new Integer(0);
    fieldvalues_in[1] = new String("Dummy Article");

    // Store data in database
    acc.insert( fieldnames, fieldvalues_in );

    // Retrieve data
    fieldvalues_out = acc.select( fieldnames, "test_id", (new Integer(0)) );

    // display
    System.out.println( ((Integer) fieldvalues_out[0]).toString() );
    System.out.println( ((String) fieldvalues_out[1]) );

    return;
  }

  // Establish the JDBC connection object to the database

  private Connection getConn() throws Exception {

    Class.forName(DRIVER);
    Connection conn = DriverManager.getConnection(URL, USER, PASSWD);
    return conn;

  }

  // Assembly "arg1,arg2,...argn" type of string  to use in
  // SQL statements from the input array of strings.

  public String getSQLList(String [] fields) throws Exception {

    StringBuffer result = new StringBuffer();
    for (int i = 0; i < fields.length -1; i++) {
      result.append( fields[i] );
      result.append( " , " );
    }
    result.append( fields[fields.length-1] );
    return result.toString();

  }

  public boolean insert (String [] fieldnames,
                         Object [] fieldvalues) throws Exception {

    // Generate an array of question marks for the SQL template parameters
    String [] paras = new String[fieldnames.length];
    for (int i = 0; i < fieldnames.length; i++) {
      paras[i] = "?";
    }

    // Prepare the template
    String SQLstr = "INSERT INTO " + TABLENAME + " ( " +
                    getSQLList(fieldnames) + " ) VALUES ( " +
                    getSQLList(paras) + " ) ";
    Connection conn = getConn();
    PreparedStatement pstmt = conn.prepareStatement(SQLstr);
    // set parameter values
    for (int i = 0; i < fieldnames.length; i++) {
      pstmt.setObject(i + 1, fieldvalues[i]);
    }
    // execute SQL statement
    boolean succ = pstmt.execute();
    pstmt.close();
    conn.close();

    return succ;
  }

  public Object [] select (String [] fieldnames, String idFieldname,
                           Object idValue) throws Exception {

    Object [] result = new Object [fieldnames.length];

    // Prepared the template
    String SQLstr = "SELECT " + getSQLList(fieldnames) + " FROM " +
                    TABLENAME + " WHERE " + idFieldname + " = ?";

    Connection conn = getConn();
    PreparedStatement pstmt = conn.prepareStatement(SQLstr);
    // set parameter value
    pstmt.setObject(1, idValue);

    // execute SQL statement
    ResultSet rs = pstmt.executeQuery();
    // go to the first record
    rs.next();
    for ( int i = 0; i < fieldnames.length; i++) {
      result[i] = rs.getObject(i+1);
    }
    rs.close();
    pstmt.close();
    conn.close();

    return result;
  }

}


[/EDIT]
 
Laatst bewerkt:
Je gebruikt een prepareStatement dit is een alternatief op het zelf aan elkaar plakken van de SQL.. Je gebruikt deze dit op de volgende manier:

Code:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                                     SET SALARY = ? WHERE ID = ?");
   pstmt.setBigDecimal(1, 153833.00)  // vult de waarde in van eerste ?
   pstmt.setInt(2, 110592) // vult de waarde in van tweede ?
   pstmt.executeUpdate();

Het is wel een goed idee om alle SQL in 1 file te houden. Zelf gebruikte ik hiervoor een property file, maar als het er niet veel zijn zou je mischien ook een Class kunnen overwegen met alle SQL als "final static String" constants.

Een preparedStatement heeft 2 belangrijke voordelen:
- Sneller de SQL wordt 1x vertaald en kan je meerdere keren uitvoeren met verschillende parameters. ("aan elkaar plak" SQL wordt elke keer vertaald)
- Veiliger, geen SQL-injection mogelijk.. "select * from user where name = '" + name + "'". kan hele leuke effecten geven als een (slimme) gebruiker als name opgeeft "Jan' ; drop table user" ;)

Maar als je vergeet de "?" in te vullen krijgen je dus jouw error...
 
Wordt een ? in een query gebruikt als een soort variabele ?
Dit is dus eigenlijk wat er ingevuld moet worden ?

Als dat zo is kun je dat dan ook gebruiken ipv je operatoren ?
Dan krijg je dus iets als :

Code:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                                     SET SALARY = ? WHERE NAME ? ?");
   pstmt.setBigDecimal(1, 153833.00)  // vult de waarde in van eerste ?
   pstm.setString(2, "LIKE") // hier kun je dus flexibel zijn door LIKE, <, >, = te gebruiken ?
   pstmt.setInt(3, 110592) // vult de waarde in van derde ?
   pstmt.executeUpdate();
 
Ja de ? is een variable en maar je kan deze niet gebruiken voor je LIKE statement.

Je kan wel zoiets voor elkaar krijgen maar is erg lelijk..

select * from user where ( ? and name like ?) or (? and leeftijd < ? )

door in de eerste of derde ? een true or false te zetten kan je dit deel van de vergelijk "aan" of "uit" zetten...
 
Maar betekent dit dan dat je niet een method kan schrijven die (op een enkele uitzondering na) al je select queries afhandeld en eentje die al je insert queries afandeld enz. ?
Of is hier een andere manier voor ?
 
Je kan wel een functie maken voor al je select statement maar dan kan je niet je prepareStatement gebruiken en moet je Statement gebruiken en je SQL als strings aan elkaar plakken.

Er zijn ook tools beschikbaar die een database table op java klasse mappen. In netbeans zitten deze ingebouwd. Geloof dat ze entityklassen heten of zoiets, je moet maar even zoeken in de netbeans tutorials op persistence.
 
Ik ben met een Lesson van Sun bezig over JDBC en daar zal er vast ook wel iets over gezegd worden.
Zo niet dan ga ik hier wel even naar kijken.
Ik had gehoopt dat het simpeler kon.

Het is natuurlijk handig als je een aantal standaard methoden hebt om te gebruiken voor je database afhandeling. Dit komt nog wel dan.

Heel erg bedankt voor je hulp en het delen van je kennis.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan