06. marts 2003 - 12:43
Der er
87 kommentarer og 1 løsning
PreparedStatement
Jeg har lavet en klasse som håndterer databaseforbindelser og som har en række metoder indbygget. På grund af nogle formaterindsproblemer er jeg blevet rådet til at bruge PreparedStatement istedet for Statement. Det er her kæden hopper af :-( Jeg håber der er en som kan hjælpe mig. Jeg opretter databaseforbindelsen sådan her try { Class.forName(driver); conn = DriverManager.getConnection(data, "", ""); } catch(Exception s) { System.out.println("SQL dataforbindelse fejlede"+s); } og jeg har så f.eks en metode som ser således ud public ResultSet select(String sql) { ResultSet r = null; try { PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, value); r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; } Den ved jo bare ikke hvad value er, og det er også det jeg ikke forstår?
Annonceindlæg tema
Forsvar & beredskab
Cybersikkerhed, realtidsdata og robuste it-systemer er blevet fundamentet for moderne forsvar.
06. marts 2003 - 12:46
#1
value er en variabel som du forsøger at tilgå - uden at have den erklæret et sted. du kunne udvide: public ResultSet select(String sql) til public ResultSet select(String sql, String value) men så skal du huske at overføre den værdi du vil sætte ind i kaldet af metoden
06. marts 2003 - 12:50
#2
Okay, men jeg forstår stadig ikke hvad jeg skal bruge den til :-) Kan jeg bare undlade pstmt.setString(1, value); ? Hvis jeg nu udvider funktionen hvad skulle jeg så f.eks sætte value til ?
06. marts 2003 - 12:52
#3
Det er hvad jeg kan læse mig til setString public void setString(int parameterIndex, String x) throws SQLExceptionSets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends it to the database. Parameters: parameterIndex - the first parameter is 1, the second is 2, ... x - the parameter value Throws: SQLException - if a database access error occurs
06. marts 2003 - 13:03
#4
pstmt.setString(1, value) benyttes når dit SQL udtryk indeholder en eller flere parametre. f.eks. "SELECT felt1, felt2, felt3 FROM mytable WHERE felt4=? AND felt5=?" Her skal du så tilføje pstmt.setString(1, value2) og pstmt.setString(2, value2) for hhv. første og anden parameter. Hvis du ingen parametre(?) har i din SQL kan/skal du ikke kalde nogen setString (eller setFelttype)
06. marts 2003 - 13:10
#5
min sql ser sådan ud d.select("SELECT * FROM tracks WHERE name='" + name + "' AND url='" + url + "'" );
06. marts 2003 - 13:17
#6
hvis du så skulle lave det om ville det blive til: d.select("SELECT * FROM tracks WHERE name=? AND url=?", name, url); i metoden: public ResultSet select(String sql, String name, String url) { ResultSet r = null; try { PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, name); pstmt.setString(2, url); r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; }
06. marts 2003 - 13:19
#7
når du benytter preparedstatements, bør du flytte den slags parametre ud af din SQL, så du får: "SELECT * FROM tracks WHERE name=? AND url=?" (bemærk ingen quotes omkring parametrene). så skal du benytte: pstmt.setString(1, name); pstmt.setString(2, url);
06. marts 2003 - 13:20
#8
din metode er quick and dirty; at binde parametrene er især hvis du skal fyre samme sætning af flere gange, da sql-udtrykke bliver oversat på databaser-serveren og så bindes værdierne til denne preparedStatement.
06. marts 2003 - 13:21
#9
Du kan evt. ændre dit metodekald til: public ResultSet select(String sql, Vector params) og benytte: for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, params.elementAt(i)); // forudsætter at alle parametre er String }
06. marts 2003 - 13:30
#10
så ser den sådan ud public ResultSet select(String sql, Vector params) { ResultSet r = null; try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, params.elementAt(i)); // forudsætter at alle parametre er String } r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; }
06. marts 2003 - 13:37
#11
setString(int,java.lang.String) in java.sql.PreparedStatement cannot be applied to (int,java.lang.Object)
06. marts 2003 - 13:39
#12
pstmt.setString(i+1, params.elementAt(i)); ændres til pstmt.setString(i+1, (String)params.elementAt(i));
06. marts 2003 - 13:44
#13
Så prøver jeg at kalde den sådan her
Databaseforbindelsemysqlprepared d = new Databaseforbindelsemysqlprepared("jdbc:
mysql://80.196.138.136/mortal?user=mik&password=mik" ,"org.gjt.mm.mysql.Driver");
String url = file.getFileName();
// .replaceAll("'","");
ResultSet rs = d.select("SELECT * FROM tracks WHERE name='" + name + "' AND url='" + url + "'" );
if (! rs.next()) {
d.insertUpdate("INSERT INTO tracks (name,url) VALUES ('"+name+"','"+url+"')");
System.out.println("raekken fandtes ikke om er oprettet!");
}
}
06. marts 2003 - 13:48
#14
Hov der kom jeg til at trykke på udfør lidt for hurtigt
06. marts 2003 - 13:51
#15
String url = file.getFileName(); // .replaceAll("'",""); ResultSet rs = d.select("SELECT * FROM tracks WHERE name=? AND url=?", name, url); if (! rs.next()) { d.insertUpdate("INSERT INTO tracks (name,url) VALUES ('"+name+"','"+url+"')"); System.out.println("raekken fandtes ikke om er oprettet!"); } } else { out.println("No uploaded files"); }
06. marts 2003 - 19:12
#16
Hvad sker der her?
06. marts 2003 - 19:22
#17
Eksperten har vistnok et "mindre" database problem ! :-)
06. marts 2003 - 19:27
#18
Ja det ser lidt sådan ud. Jeg kan stadig ikke få den der PreparredStatement vil at makke ret :-(
06. marts 2003 - 19:37
#19
Jeg kan kun se indlæg fra 19:12:49 ! Hvad er problemet ?
06. marts 2003 - 19:40
#20
Jeg har lavet en separat klasse til at håndterer det som ser således ud package util; import java.util.Vector; import java.sql.*; public class Databaseforbindelsemysqlprepared { private Connection conn ; private PreparedStatement pstmt; public Databaseforbindelsemysqlprepared(String data, String driver) { try { Class.forName(driver); conn = DriverManager.getConnection(data, "", ""); } catch(Exception s) { System.out.println("SQL dataforbindelse fejlede"+s); } } public ResultSet select(String sql, Vector params) { ResultSet r = null; try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, (String)params.elementAt(i)); // forudsætter at alle parametre er String } r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; } public void insertUpdate(String sql) { try { pstmt.executeUpdate(sql); } catch(SQLException s) { System.out.println("update/insert fejlede"); } } public void close() { try { pstmt.close(); } catch(SQLException s) { System.out.println("Close fejlede"); } } }
06. marts 2003 - 19:40
#21
og jeg kalder den således String url = file.getFileName(); // .replaceAll("'",""); Vector vi = new Vector(); vi.addElement(name); vi.addElement(url); ResultSet rs = d.select("SELECT * FROM tracks WHERE name='" + name + "' AND url='" + url + "'", vi); if (! rs.next()) { d.insertUpdate("INSERT INTO tracks (name,url) VALUES ('"+name+"','"+url+"')"); System.out.println("raekken fandtes ikke om er oprettet!"); } } else { out.println("No uploaded files"); }
06. marts 2003 - 19:41
#22
den uploader faktiskt selve filen men den opdaterer ikke databasen
06. marts 2003 - 19:44
#23
Hvor er spørgsmåls-tegnene i SQL'en ?
06. marts 2003 - 19:44
#24
Jeg tro du vil lave: Vector vi = new Vector(); vi.addElement(name); vi.addElement(url); ResultSet rs = d.select("SELECT * FROM tracks WHERE name=? AND url=?", vi);
06. marts 2003 - 19:44
#25
hvad betyder ? i sql'en i den forbindelse ?
06. marts 2003 - 19:46
#26
Det er hele tricket man skiver bare et spørgsmåls-tegn i SQL og så bruger man setXxxx til at putte data ind i.s.f. spørgsmåls-tegn.
06. marts 2003 - 19:49
#27
? betyder nærmst "sæt plads af til em værdi". Det kan bruges til 2 ting: 1) Man kan bruge den samme prepared statement med forskellige værdier for ? hvillket giver bedre performance end separate statements. 2) Der er ingen quotes i SQL og quotes i værdier er ikke noget problem, hvilket løser quote/pling/apostrof problemer.
06. marts 2003 - 19:51
#28
Det vil stadig ikke virke
06. marts 2003 - 19:53
#29
Der går et eller andet galt med tegnene
06. marts 2003 - 19:57
#30
Har du konverteret insertUpdate ?
06. marts 2003 - 19:58
#31
Altså så SQL har 2 x ? og din vektor kommer over som argument og setString kaldes i et loop ligesom for select ?
06. marts 2003 - 20:00
#32
Ømmm næ, tror jeg nok :-)
06. marts 2003 - 20:03
#33
Det må jeg prøve
06. marts 2003 - 20:05
#34
d.insertUpdate("INSERT INTO tracks (name,url) VALUES (?,?)", vi); public void insertUpdate(String sql, Vector params) { try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, (String)params.elementAt(i)); } pstmt.executeUpdate(); } catch(SQLException s) { System.out.println("update/insert fejlede"); } }
06. marts 2003 - 20:12
#35
øv det virker ikke :-(
06. marts 2003 - 20:18
#36
Den sætter mærkelige tegn ind
06. marts 2003 - 20:19
#37
Hvilke mærkelige tegn ? Kunen du give et eksempel på det den sætter ind og hvad det skulle have været ?
06. marts 2003 - 20:20
#38
Ja da, øjeblik
06. marts 2003 - 20:23
#39
error near '
06. marts 2003 - 20:23
#40
Den smider en exception
06. marts 2003 - 20:24
#41
06. marts 2003 - 20:25
#42
Kan du lige poste koden igen som den ser ud nu ?
06. marts 2003 - 20:25
#43
package util; import java.util.Vector; import java.sql.*; public class Databaseforbindelsemysqlprepared { private Connection conn ; private PreparedStatement pstmt; public Databaseforbindelsemysqlprepared(String data, String driver) { try { Class.forName(driver); conn = DriverManager.getConnection(data, "", ""); } catch(Exception s) { System.out.println("SQL dataforbindelse fejlede"+s); } } public ResultSet select(String sql, Vector params) { ResultSet r = null; try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, (String)params.elementAt(i)); // forudsætter at alle parametre er String } r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; } public void insertUpdate(String sql, Vector params) { try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, (String)params.elementAt(i)); } pstmt.executeUpdate(); } catch(SQLException s) { System.out.println("update/insert fejlede"); } } public void close() { try { pstmt.close(); } catch(SQLException s) { System.out.println("Close fejlede"); } } }
06. marts 2003 - 20:26
#44
if (MultipartFormDataRequest.isMultipartFormData(request))
{
// Uses MultipartFormDataRequest to parse the HTTP request.
Vector listeners = new Vector();
listeners.addElement(upListener);
MultipartFormDataRequest mrequest = new MultipartFormDataRequest(request,listeners);
String todo = mrequest.getParameter("todo");
String name = mrequest.getParameter("name");
if ( (todo != null) && (todo.equalsIgnoreCase("upload")) )
{
Hashtable files = mrequest.getFiles();
if ( (files != null) || (!files.isEmpty()) )
{
UploadFile file = (UploadFile) files.get("uploadfile");
out.println("Form field : uploadfile"+"<BR> Uploaded file : "+file.getFileName()+" ("+file.getFileSize()+" bytes)"+"<BR> Content Type : "+file.getContentType());
// Uses the bean now to store specified by jsp:setProperty at the top.
upBean.store(mrequest, "uploadfile");
out.println("<br>Name of song: "+name);
Databaseforbindelsemysqlprepared d = new Databaseforbindelsemysqlprepared("jdbc:
mysql://URL/DB?user=user&password=pass" ,"org.gjt.mm.mysql.Driver");
String url = file.getFileName();
// .replaceAll("'","");
Vector vi = new Vector();
vi.addElement(name);
vi.addElement(url);
ResultSet rs = d.select("SELECT * FROM tracks WHERE name=? AND url=?", vi);
//ResultSet rs = d.select("SELECT * FROM tracks WHERE name='" + name + "' AND url='" + url + "'", vi);
if (! rs.next()) {
d.insertUpdate("INSERT INTO tracks (name,url) VALUES (?,?)", vi);
//d.insertUpdate("INSERT INTO tracks (name,url) VALUES ('"+name+"','"+url+"')");
System.out.println("raekken fandtes ikke om er oprettet!");
}
}
else
{
out.println("No uploaded files");
}
}
else out.println("<BR> todo="+todo);
}
%>
06. marts 2003 - 20:30
#45
Det ser umiddelbart meget OK ud. Hvad er den exception tekst du får ud ?
06. marts 2003 - 20:35
#46
06. marts 2003 - 20:41
#47
Der er ingen problemer hvis der ingen pinger er
06. marts 2003 - 20:47
#48
06. marts 2003 - 20:48
#49
altså den jeg tester på :-)
06. marts 2003 - 20:49
#50
06. marts 2003 - 20:56
#52
prøv lige igen :-)
06. marts 2003 - 20:59
#53
No luck.
06. marts 2003 - 21:00
#54
Bruger du MySQL ?
06. marts 2003 - 21:01
#55
06. marts 2003 - 21:02
#56
Jeg prøver lige at genstarte serveren
06. marts 2003 - 21:05
#57
nu burde det virke
06. marts 2003 - 21:05
#58
Jeg kan også sende det til dig i en mail
06. marts 2003 - 21:08
#59
Jeg får stadigvæk "connection refused". arne_v@mail.danbbs.dk
06. marts 2003 - 21:08
#60
nå?
06. marts 2003 - 21:10
#61
Kan det være fordi jeg har Block WAN Requests enabled i min router?
06. marts 2003 - 21:11
#62
Ja !
06. marts 2003 - 21:13
#63
Men jeg har modtaget email, så no problem.
06. marts 2003 - 21:15
#64
kan du komme ind nu?
06. marts 2003 - 21:16
#65
Det er allerede på SELECT statement at det går galt. Og der er noget galt. Den skriver: AND url='12 hvordan kan en URL starte med 12 ??
06. marts 2003 - 21:17
#66
Ja - det virker fint.
06. marts 2003 - 21:18
#67
Jeg prøvede lige at lave følgende:
import java.sql.*;
public class QuoteInsert {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:
mysql://localhost/Test" , "", "");
PreparedStatement pstmt = con.prepareStatement("INSERT INTO Benchmark VALUES (?, ?)");
long t1 = System.currentTimeMillis();
for(int i = 0; i < 10; i++) {
pstmt.setInt(1, i);
pstmt.setString(2, "''''''");
pstmt.executeUpdate();
}
pstmt.close();
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
og når jeg kører det så havner der 10 x 6 plinger i tabellen.
06. marts 2003 - 21:18
#68
godt spørgsmål
06. marts 2003 - 21:21
#69
Kan vi prøve med en debug version: public ResultSet select(String sql, Vector params) { ResultSet r = null; try { System.out.println("SQL=" + sql); PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { SYstem.out.println("arg " + (i + 1) + "=" + (String)params.elementAt(i)); pstmt.setString(i+1, (String)params.elementAt(i)); } r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; }
06. marts 2003 - 21:21
#70
min tabel jeg ligger det ned i har 3 kolononer den første er et tal som tæller en op for hver rækker der bliver sat ind og de to andre er varchars
06. marts 2003 - 21:24
#71
så er den nye kode lagt ind
06. marts 2003 - 21:25
#72
Men at du har et tal i tabellen skulle jo ikke påvirke WHERE betingelsen i SELECT.
06. marts 2003 - 21:27
#73
Svaret er at det kun er det sidste af urlen 12. I don't wanna live forever.mp3
06. marts 2003 - 21:29
#74
Hvad printede de 3 print statements ?
06. marts 2003 - 21:31
#75
en ' og det går helt i sort.
06. marts 2003 - 21:33
#76
de printede ingenting
06. marts 2003 - 21:35
#77
Ingenting ? Jeg er forvirret nu !
06. marts 2003 - 21:39
#78
også mig
06. marts 2003 - 21:39
#79
package util; import java.util.Vector; import java.sql.*; public class Databaseforbindelsemysqlprepared { private Connection conn ; private PreparedStatement pstmt; public Databaseforbindelsemysqlprepared(String data, String driver) { try { Class.forName(driver); conn = DriverManager.getConnection(data, "", ""); } catch(Exception s) { System.out.println("SQL dataforbindelse fejlede"+s); } } public ResultSet select(String sql, Vector params) { ResultSet r = null; try { System.out.println("SQL=" + sql); PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { System.out.println("arg " + (i + 1) + "=" + (String)params.elementAt(i)); pstmt.setString(i+1, (String)params.elementAt(i)); } r = pstmt.executeQuery(); } catch(SQLException s) { System.out.println("Select fejlede: "+s); } return r; } public void insertUpdate(String sql, Vector params) { try { PreparedStatement pstmt = conn.prepareStatement(sql); for (int i=0; i < params.size(); i++) { pstmt.setString(i+1, (String)params.elementAt(i)); } pstmt.executeUpdate(); } catch(SQLException s) { System.out.println("update/insert fejlede"); } } public void close() { try { pstmt.close(); } catch(SQLException s) { System.out.println("Close fejlede"); } } }
06. marts 2003 - 21:42
#80
og i jsp Vector vi = new Vector(); vi.addElement(name); vi.addElement(url); ResultSet rs = d.select("SELECT * FROM tracks WHERE name=? AND url=?", vi); if (! rs.next()) { d.insertUpdate("INSERT INTO tracks (name,url) VALUES (?,?)", vi); System.out.println("raekken fandtes ikke om er oprettet!"); } }
06. marts 2003 - 21:47
#81
Jeg tror muligvis det kunne være givtigt at separere tingene lidt. Kunne du prøve at lave et ganske almindeligt standalone Java program som bruger din DB klasse til at lave en select og en insert med plinger i ? Når vi så har fået det til at virke, så går vi tilbag etil JSP. Det er langt nemmere og hurtigere at debugge en lille test app end end web app.
06. marts 2003 - 21:53
#82
okay, men jeg er ærlig talt lidt træt i hovedet lige nu, så jeg tror jeg venter til i morgen :-)
06. marts 2003 - 21:59
#83
Det lyder som en rigtig god ide.
06. marts 2003 - 21:59
#84
ja ikke :-))))
06. marts 2003 - 22:10
#85
Helt ufattelig at en ' kan lave så meget ravage ;-)
06. marts 2003 - 22:16
#86
Jeg tror altså stadigvæk at ' er løst med prepared statement, men at det er noget andet som driller med prepared statement.
07. marts 2003 - 12:59
#87
JUBIIIIII Nu virker det. Jeg lavede lige et lille Swing Interface og kunne konstaterer at der ikke var nogle problemer. Grunden til at den klippede af ved første ' når den skulle vise det var at jeg havde skrevet således out.println("<a href='../music/"+url+"'>download"); Så er det jo klart at den tror at der ikke er mere når den løber ind i en ' det har jeg så ændret til out.println("<a href=\"../music/"+url+"\">download"); Hvorfor den ikke ville opdaterer databasen (i forbindelse med en upload) før er et mysterie for mig. Tusinde tak for hjælpen og læg lige et svar så jeg kan give dig pointene
07. marts 2003 - 13:13
#88
Jeg kunne heller ikke forstå at quotes gav problemer med prepared statement. Men godt at det virker.
Kurser inden for grundlæggende programmering