I am trying to use the preparedStatement Batch but I am having a problem.
The following code does not give me errors, but it inserts in the table only last key of the map and I do not know why.
It will be surely a very stupid error, but this is the first time I use the addBatch() method..
Class.forName("com.mysql.jdbc.Driver");
this.connect = DriverManager.getConnection("jdbc:mysql://localhost/" + this.database + "?user=" + this.user + "&password=" + this.password);
String s;
for (String key : this.map.keySet())
{
s = ("insert into " + this.database + ".user (nickname) values (?)");
this.preparedStatement = this.connect.prepareStatement(s);
this.preparedStatement.setString(1, key);
this.preparedStatement.addBatch();
}
this.preparedStatement.executeBatch();
Thanks in advance!
Prepare your Statement and query outside of the loop:
s = ("insert into " + this.database + ".user (nickname) values (?)");
this.preparedStatement = this.connect.prepareStatement(s);
for (String key : this.map.keySet())
{
this.preparedStatement.setString(1, key);
this.preparedStatement.addBatch();
}
this.preparedStatement.executeBatch();
You are using the addBatch() method wrong. In your code you are doing the prepareStatement in each iteration of for loop, and this replaces the prepared query each time.
You should only be calling prepareStatement once per batch. You should place the prepared statement before the loop (only one call)
Related
List<Guest> guestList = new ArrayList<>();
String query = "select * from Guests where ? like ?";
System.out.println("select * from Guests where " + property + " like '%" + value + "%'");
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, property);
preparedStatement.setString(2, "'%" + value + "%'");
ResultSet resultSet = preparedStatement.executeQuery();
guestList = getGuestListFromResultSet(resultSet);
return guestList;
As you can see above, I created a Prepared Statement, which is later populated with 2 values: property and value. Running the above query should give me some results in SQL Server.
I also tried these variations for setting the second parameter(value):
preparedStatement.setString(2, "%" + value + "%");
preparedStatement.setString(2, value);
None of these seem to work. What does work is simply building the query from string concatenation:
PreparedStatement preparedStatement = connection.prepareStatement("select * from Guests where " + property + " like '" + value + "'");
However, I want to use a Prepared Statement.
You can't use a variable as a column name. Instead, you can use dynamic SQL
String query = """
DECLARE #sql nvarchar(max) = '
select *
from Guests
where ' + QUOTENAME(?) + ' like #value;
';
EXEC sp_executesql #sql,
N'#value nvarchar(100)',
#value = ?;
""";
Note the use of QUOTENAME to correctly escape the column name.
Note also the use of sp_executesql to pass the value all the way through.
I'm not sure about the JDBC driver, but ideally you should use proper named parameters, rather than ?
Currently, I am using for loop, which is unacceptably slow when orgList has thousands of elements inside:
String sql = "SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03=?";
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
for(HotelSource org : orgList) {
ps.setString(1, org.getPrimaryKey());
rs = ps.executeQuery();
while (rs.next()) {
// do sth
}
}
What is the right way to do the SELECT?
You should use SQL IN, for example:
SELECT ... FROM ... WHERE xua.XUA03 IN (x, y, z, ...)
You can still parameterise your query, but you need to generate the correct number of ? in the statement. So some psuedocode here because I don't do Java:
String params = "?, ?, ?, ?"; //you will have to generate enough of these yourself
//This is an exercise for you!
String sql = "SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03 IN (" + params + ")";
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
int index = 1;
for(HotelSource org : orgList) {
ps.setString(index, org.getPrimaryKey());
// ^^^^^ use index here
index++;
}
rs = ps.executeQuery();
while (rs.next()) {
// do sth
}
Note: The downside of this is that you mention you have thousands of entries in orgList which makes it really bad practice to use this method. In fact, SQL Server will not allow you to use more than a couple of thousand parameters.
Use IN operator no need to hit the query for each value
SELECT xua.XUAID, xua.XUA01, xua.XUA02
FROM dbo.XDSysUseArea xua
WHERE xua.XUA03 in (val1,val2,val3,..) -- pass the list here
Store org.getprimarkey() in a arraylist List<Integer> past it to where clause using in operator
SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03 IN (mylist);
NOTE: replace [ ] in list using replaceall method.
You can use operator IN for this purpose. Example,
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1, value2, ...);
I've got the following code in my app
String sql = "SELECT colA, colB, colC " +
"FROM " + tblName + " WHERE UserId = " + userId +
" AND InsertTimestamp BETWEEN " + lastDate +
" AND " + DataProcessor.TODAY + " ORDER BY UserId, Occurred";
try{
if(null == conn)
openDatabaseConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery(); <------- this is the line which throws the SQL exception
retArray = this.getArrayListFromResultSet(rs);
}catch(SQLException sqle){
JSONObject parms = new JSONObject();
eh.processSQLException(methodName, sqle, sql, parms);
}
So when I run my app in the debugger, I get this exception message
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00.0 AND 2014-08-20 00:00:00.0 ORDER BY UserId, Occurred' at line 1
I'm reasonably certain that there's simple and reasonable solution to this, but I have not been able to find it.
I've tried looking in the MySQL manual for a solution or a different format.
I've tried running my timestamps through a TIMESTAMP() functino and a DATE() function in the SQL, neither of which helped.
I pulled the fully formed SQL out of the Java code and ran it in MySQL Workbench with no issues, what-so-ever. So now I'm looking to the experts for help.
Dates in SQL must be enclosed within single quotes like strings.
As you're using a prepared statemtent, why you don't use '?' and stmt.setDate(...)?
String sql = "SELECT colA, colB, colC " +
"FROM " + tblName + " WHERE UserId = ?" +
" AND InsertTimestamp BETWEEN ?" +
" AND ? ORDER BY UserId, Occurred";
try {
if(null == conn) {
openDatabaseConnection();
}
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
stmt.setDate(2, lastDate);
stmt.setDate(3, DataProcessor.TODAY);
ResultSet rs = stmt.executeQuery();
retArray = this.getArrayListFromResultSet(rs);
} catch(SQLException sqle) {
JSONObject parms = new JSONObject();
eh.processSQLException(methodName, sqle, sql, parms);
}
Anyway, I think you are setting the dates in the opposite order. You should put first 'today' then lastDate. Although I don't know your constraints...
what's wrong with my insert method?
my table has two columns, name, and artist..and timestamp, that too
actually, how do i pass timestamp argument to the insert statement?
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
/*FileWriter dir = new FileWriter(nameOfSong.getText()
+ ".txt");
BufferedWriter buffer = new BufferedWriter(dir);
buffer.write(nameOfSong.getText());
buffer.newLine();
buffer.write(artist.getText());
buffer.newLine();
buffer.newLine();
buffer.write(lyrics.getText());
buffer.close();
*/
Statement statement = connection.createStatement();
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES(" +
nameOfSong.getText() + ", " + artist.getText() + "");
} catch (Exception z) {
System.err.println("Error: " + z.getMessage());
}
internalFrame.dispose();
}
});
)
Always use PreparedStatement.
String sql="INSERT INTO lyrics1_lyrics1 VALUES (?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,nameOfSong.getText());
statement.setString(2,artist.getText());
statement.executeUpdate();
statement.close();
connection.close();
The text values need to be surrounded by single quotes ('').
And SQL-escaped to avoid SQL injection attacks, or the first time you have a song by Little Bobby Tables, all your DB are belong to him.
Better yet, use a PreparedStatement, and let the machine do work for you.
You can use prepared statement for it
String query = "INSERT INTO lyrics1_lyrics1(name, artist, timestamp) values(?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, name); // set input parameter 2
pstmt.setString(2, artist);
pstmt.setString(3, new TimeStamp(new Date().getTime()));
You need to add an import statement for the TimeStap;
import java.sql.Timestamp;
or else use
pstmt.setString(3, new java.sql.TimeStamp(new Date().getTime()));
Example: Prepared Statement Insert.
You can find a lot of example in java2s site.
Change the line to:
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES('" +
nameOfSong.getText() + "', '" + artist.getText() + "'");
This might solve your problem:
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES('" + nameOfSong.getText() + "', '" + artist.getText() + "')");`
while (tokens.hasMoreTokens())
{
keyword = tokens.nextToken();
System.out.println("File= "+fileid+" Keyword=" + keyword);
stmt.executeUpdate(
"INSERT into TEXTVALUEINVERTEDINDEX " + "(FILEID, KEYWORD) values ('"
+ fileid + "', '" + keyword + "')"
);
}
This is the loop in which I'm updating the rows. The problem I'm facing is that when i run this only 1 value gets updated and when I comment the stmt.executeUpdate() line it displays all the possible entries in the database.
You need to use preparedStatements...
PreparedStatement pStmt = connection.prepareStatement("INSERT into TEXTVALUEINVERTEDINDEX (FILEID, KEYWORD) values(?,?)");
while (tokens.hasMoreTokens())
{
keyword = tokens.nextToken();
System.out.println("File= "+fileid+" Keyword="+keyword);
pStmt.setString(1, fileid); //This might be pStmt.SetInt(0, fileid) depending on teh type of fileid)
pStmt.setString(2, keyword);
pStmt.executeUpdate();
}
then using this you can extend to us batch update...
PreparedStatement pStmt = connection.prepareStatement("INSERT into TEXTVALUEINVERTEDINDEX (FILEID, KEYWORD) values(?,?)");
while (tokens.hasMoreTokens())
{
keyword = tokens.nextToken();
System.out.println("File= "+fileid+" Keyword="+keyword);
pStmt.setString(1, fileid); //This might be pStmt.SetInt(0, fileid) depending on teh type of fileid)
pStmt.setString(2, keyword);
pStmt.addBatch();
}
pStmt.executeBatch();
Not sure why your code isn't working though - but this will probably help in the long run...
Your code should work. Make sure the sentence is not throwing any Exceptions when running by surrounding it with a try/catch block:
try {
stmt.executeUpdate("INSERT into TEXTVALUEINVERTEDINDEX " +
"(FILEID, KEYWORD) "+"values ('"+fileid+"', '"+keyword+"')");
} catch (SQLException e) {
e.printStackTrace();
}
You should also consider using a PreparedStament instead since its use is very appropriate for your described scenario:
Something like this:
String sql = "insert into textvalueinvertedindex (fileid, keyword) values (?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
while (tokes.hasMoreTokens()) {
keywords = tokens.nextToken();
pstmt.setString(1, fileid);
pstmt.setString(2, keyword);
pstmt.executeUpdate();
}
pstmt.close();
If you want all updates to be applied at once you can use batch execution, here is an example
Your date range and filter selection contained no results.