Avatar billede rasmuslh Nybegynder
17. maj 2004 - 10:49 Der er 16 kommentarer og
1 løsning

Servletter gengrug af Statements

Hejsa

Jeg sidder og arbejder med et projekt i MySQL og Servletter. Jeg har en abstrakt klasse MainServlet der erklærer:

  public static Statement    st;   


Det statement vil jeg gerne genbruge i alle de Servletter der extender MainServlet til at kommunikere med databasen.

Jeg har en række SQL'er som executes vha. statementet og gemmer resultatet i et Resultset, men hvis jeg genbruger Statementet gemmes der ikke noget i det "første" Resultset.

F.eks.:
          st.execute(query1);
          ResultSet rs1 = st.getResultSet();
          st.execute(query2);
          ResultSet rs2 = st.getResultSet();

Hvis jeg gør det på denne måde er rs1 tomt når jeg prøver at hente det første Resulset.

Hvis jeg derimod erklærer det sådan her:

          st1.execute(query1);
          ResultSet rs1 = st1.getResultSet();
          st2.execute(query2);
          ResultSet rs2 = st2.getResultSet();

Virker det fint!

Kan man ikke genbruge Statementet eller gør jeg bare noget forkert.

MVH.
Rasmus
Avatar billede arne_v Ekspert
17. maj 2004 - 11:11 #1
Der er normalt ikke nogen grund til at genbruge Statement, da det ikke koster
noget at oprette et sådant.

Jeg tror grundliggende at jeres problem er at et ResultSet ikke indeholder
resulatet af en query, men kun en pege pind til hvor lang man er kommet med
at hente resultatet. Det er next som faktisk henter data. Man skal derfor
enten køre et result set færdigt eller have 2 connections, 2 statement og
2 results et.

Personligt bruger jeg normalt:
  ResultSet rs = stmt.executeQuery();

Har I overvejer jeres kode i en multithreaded context ?
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 11:16 #2
Okay, det forklarer en del da vi i de tilfælde jeg har testet har begge while efter:

          st.execute(query1);
          ResultSet rs1 = st.getResultSet();
          st.execute(query2);
          ResultSet rs2 = st.getResultSet();

har det nogen betydning om man bruger:

      ResultSet rs = stmt.executeQuery();
      eller
      st1.execute(query1);
      ResultSet rs1 = st1.getResultSet();

Og hvad mener du med det her:
"Har I overvejer jeres kode i en multithreaded context ?"
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 11:17 #3
... og endnu engang tak for de hurtige svar!!!

På forhånd tak
Rasmus
Avatar billede arne_v Ekspert
17. maj 2004 - 11:21 #4
execute() og getResultSet() bruger man normalt med stored procedures som
kan returnere flere result set.

executeQuery bruger man ved normale queries som returnerer et enkelt result set.

Der er ingen funktionel forskel så vidt jeg ved.
Avatar billede arne_v Ekspert
17. maj 2004 - 11:22 #5
Hvis to brugere requester samme servlet samtidigt hvad sker der så med:

public static Statement    st;

?
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 11:46 #6
Er det her SingleThread kommer ind i billedet?
Avatar billede arne_v Ekspert
17. maj 2004 - 12:20 #7
Hvis du implements SingleThreadModel og laver public static Statement    st; om til
public Statement    st (uden static), så begynder det at ligne noget.

Selvom løsningen stadig er en anelse utraditionel.
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 12:26 #8
Har du et andet forslag????? ;-D
Avatar billede arne_v Ekspert
17. maj 2004 - 12:34 #9
Den traditionelle løsning er:
  - connections fra connection pool
  - statements og result set som variable indeni metoderne
hvilket er thread safe uden brug af SingleThreadModel
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 12:45 #10
Du har evt. ikke nogle referencer til steder hvor jeg kan læser mere om det og få eksempler fordi det lyder da som en lidt smartere fremgangsmåde!

Og lav evt. et svar så du kan få point.

Tusind tak for hjælpen.
MVH.
Rasmus
Avatar billede arne_v Ekspert
17. maj 2004 - 12:57 #11
Jeg har faktisk skrevet en lille artikel som beskriver connection pool i Tomcat.

http://www.eksperten.dk/artikler/50

Brug af lokale variabele i metoderne er jo ligeud af landevejen.

Jeg kan evt. lave et komplet eksempel i aften.
Avatar billede arne_v Ekspert
17. maj 2004 - 12:57 #12
svar
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 13:02 #13
Det ville være fantastisk!!! Nu læser jeg lige lidt på artiklen!

Endnu engang tak for svarene!
MVH.
Rasmus
Avatar billede rasmuslh Nybegynder
17. maj 2004 - 14:29 #14
Hej Arne
Nu har jeg læst din artikel, men det muligt at løse Concurrency problemet uden at skulle rette i server.xml filen. Andet end ved at implemente SingleThread!

MVH.
Rasmus
Avatar billede arne_v Ekspert
17. maj 2004 - 20:34 #15
Er det et problem at rette i server.xml ?
Avatar billede arne_v Ekspert
17. maj 2004 - 20:35 #16
Avatar billede arne_v Ekspert
17. maj 2004 - 21:56 #17
Hvis I kan rette i server.xml, så følger I bare vejledningen i min artikel og
ovenstående link. Det er rimeligt veldokumenteret.

Hvis I ikke kan rette i server.xml så laver I jeres egen connection pool.

Eksempel:

import java.io.*;
import java.sql.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.dbcp.*;
import org.apache.commons.pool.impl.*;

public class PoolServlet extends HttpServlet {
    private GenericObjectPool cp;
    private DriverManagerConnectionFactory dmcf;
    private PoolableConnectionFactory pcf;
    private PoolingDataSource ds;
    public void init() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            cp = new GenericObjectPool(null);
            dmcf = new DriverManagerConnectionFactory("jdbc:mysql://localhost/Test", "", "");
            pcf = new PoolableConnectionFactory(dmcf, cp, null, null, false, true);
            ds = new PoolingDataSource(cp);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        try {
            Connection con = ds.getConnection();
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM T1");
            while (rs.next()) {
                int f1 = rs.getInt(1);
                String f2 = rs.getString(2);
                response.getWriter().println(f1 + " " + f2 + "<BR/>");
            }
            rs.close();
            stmt.close();
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
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