Java/JDBC - SQL Exception on input - java

My Insert is failing via preparedStatment, I've run the statement through MySQL manually and it works, and I've double checked my params, but it's failing when run through the app.:
try {
myConn = DriverManager.getConnection(url, username, password);
preStmt = myConn.prepareStatement(
"Insert Into games(HomeTeamID, AwayTeamID, HomeTeamGoals, AwayTeamGoals, GameMonth, GameDay, GameYear, Overtime, Shootout)
Values(?, ?, ?, ?, '?', ?, ?, ?, ?);");
preStmt.setInt(1, game.getHomeID());
preStmt.setInt(2, game.getAwayID());
preStmt.setInt(3, game.getHomeGoals());
preStmt.setInt(4, game.getAwayGoals());
preStmt.setString(5, game.getGameMonth());
preStmt.setInt(6, game.getGameDay());
preStmt.setInt(7, game.getGameYear());
preStmt.setBoolean(8, game.isOvertime());
preStmt.setBoolean(9, game.isShootout());
preStmt.executeUpdate();
myConn.commit();
}
catch(SQLException sqlex) { // FAILING ON THIS CATCH
JOptionPane.showMessageDialog(null, "Error - Game Update Failed!\n\t-> SQL Error.");
}
I've scoured numerous docs online, but couldn't find any reason why it wouldn't work, and as mentioned, I run the same statement through MySQL with mock data, and it works...
Any suggestions?

Issue Resolved:
In values(), '?' doesn't fly, was just ?
I was passing comboBox.toString(), should have been passing comboBox.getSelectedItem().toString()
commit failed after as I'd not set myConn.setAutoCommit(false);, removed myConn.commit() and now works...
Thank you for directing to stackTrace, I'd been manually debugging and spaced on checking that :/ Sorry

Related

Insert into Oracle DB using Java

I am trying to insert values in a table on my oracle server, however, the program keeps running and doesn't execute. This is my code:
This is how I connect to the database:
try {
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#abc.xxx.edu:1521:soeorcl","123",
"123");
} catch (SQLException e) {
System.out.println("Connection Failed! Check output console");
e.printStackTrace();
return;
Then I try to insert the values in the table:
try {
PreparedStatement prepareStatement = connection.prepareStatement("INSERT INTO MYTABLE (USERID, USERNAME, EMAILADDRESS, PHONENUMBER, PROFILEPICTURE )"
+ " VALUES (?, ?, ?, ?, ?)");
prepareStatement.setString(1, "10");
prepareStatement.setString(2, "ALI");
prepareStatement.setString(3, "gdgrgrregeg");
prepareStatement.setString(4, "0501977498");
prepareStatement.setNull(5, NULL);
prepareStatement.execute();
} catch (SQLException e) {
System.out.println("IT DOES NOT WORK");
}
The program gets stuck at prepareStatement.execute(); I have already checked the constraints and they work if I manually add them on the oracle server but the above code does not work.
Any ideas? Suggestions?
Try printing the sql string used in your prepared statement and then copy paste it and run it manually. Often times there are some misspellings or missing spaces in the string. In your case it could be an error from the way the statement is written.
I noticed that you need a space before VALUES.

is this actually a resource leak?

I have an "Invitation" object that is modeled in a MySQL database. This object has one list ("treatmentPlanIDsToCopyf") and is maintained in the database with a second table. The method I have written to insert into the main table and then loop through the list and insert records for each item in the list into the second table is below. At the line ps = cn.prepareStatement(sql);Eclipse is giving me a warning that says "Resource leak: 'ps' is not closed at this location". I am closing the prepared statement in the finally clause, so I wanted to know if there really is a resource leak I need to fix. This is my first time using batches with prepared statements, so I wasn't really sure. Thanks.
public void invitationCreate(Connection cn, Invitation invitation) throws SQLException{
PreparedStatement ps = null;
try {
//first insert primary invitation data into the invitation table
String sql = "INSERT INTO invitiation (invitation_code, recipient_email, sender_user_id_fk, date_intived, date_accepted, accepted, recipient_first_name, recipient_last_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
ps = cn.prepareStatement(sql);
ps.setString(1, invitation.getInvitationCode());
ps.setString(2, invitation.getRecipientEmail());
ps.setInt(3, invitation.getSenderUserID());
ps.setTimestamp(4, convertLocalTimeDateToTimstamp(invitation.getDateInvited()));
ps.setTimestamp(5, convertLocalTimeDateToTimstamp(invitation.getDateAccepted()));
ps.setBoolean(6, invitation.isAccepted());
ps.setString(7, invitation.getRecipientFirstName());
ps.setString(8, invitation.getRecipientLastName());
int success = ps.executeUpdate();
//now loop through all the treatmentPlanIDs in the invitation that are to be copied into the invitees account when the register
sql = "INSERT INTO invitation_treatment_plans (invitation_code_fk, invitation_treatment_plan_id_fk) VALUES (?, ?)";
ps = cn.prepareStatement(sql);//TODO confirm this if this is actually a resource leak
for(int treatmentPlanID : invitation.getTreatmentPlanIDsToCopy()){
ps.setString(1, invitation.getInvitationCode());
ps.setInt(2, treatmentPlanID);
ps.addBatch();
}
ps.executeBatch();
} finally {
DbUtils.closeQuietly(ps);
}
}
I believe the leak is in the first prepared statement.
After int success = ps.executeUpdate(); you need to close that prepared statement before you assign the variable to a new prepared statement.

Proper Unit Testing in void method in java without mocking

Is there a way to test a method that doesn't return any value without the use of Mockito?
This is the sample method. I'm new in Unit Testing.
public void addMantisData(ArrayList<Mantis> list) {
try {
connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection
.prepareStatement("INSERT INTO mantises (ticketId, startDate, endDate, hours, minutes, " +
"employeeId, timeIn, timeOut, dateSubmitted, category, status, timestamp) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())");
for (Mantis mantis : list) {
preparedStatement.setInt(1, mantis.getTicketId());
preparedStatement.setString(2, mantis.getStartDate());
preparedStatement.setString(3, mantis.getEndDate());
preparedStatement.setInt(4, mantis.getHours());
preparedStatement.setInt(5, mantis.getMinutes());
preparedStatement.setInt(6, mantis.getEmployeeId());
preparedStatement.setString(7, mantis.getStartTime());
preparedStatement.setString(8, mantis.getEndTime());
preparedStatement.setString(9, mantis.getDateSubmitted());
preparedStatement.setString(10, mantis.getCategory());
preparedStatement.setString(11, mantis.getStatus());
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
preparedStatement.close();
} catch (SQLException e) {
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
}
}
}
}
I apprieciate the help :)
This seems more like it would be an integration test with the DB then a pure unit test. Also im not sure what it is that you want to test, if it is the query you will need to perform the insert and then try to get expected values from the DB and assert with expected result. Make sure that you use your own instance of the DB and also rollback after the test. DBUnit will make this happen for you, check it out
If you don't want to use any "mock" or "spy" classes (hand-made or from Mockito), you could consider a "cheap" database that lives in-memory (or backed by temporary files). Then your code can issue queries via JDBC just like the real thing, and your unit test can prepare data and inspect results (also via JDBC).
Be sure to read the answers for this similar question.

General error in JDBC(updating database)

private void sUpdateBtnActionPerformed(java.awt.event.ActionEvent evt) {
String query = "UPDATE Student SET lastname = ?, firstname = ?, course = ?, yearlvl = ?, username = ?, password = ?";
dbConn = DbConnection.dbConnect();
prepState = dbConn.prepareStatement(query);
prepState.setString(1, sLnTf.getText());
prepState.setString(2, sFnTf.getText());
prepState.setString(3, courseTf.getText());
prepState.setInt(4, Integer.parseInt(yearLvlTf.getText()));
prepState.setString(5, sUserTf.getText());
prepState.setString(6, sPassTf.getText());
prepState.executeUpdate();
}catch(Exception e){
appendEvent(sdf.format(new Date()) + " Error: " + e);
}
}
Method for connecting to the database:
import java.sql.*;
import javax.swing.*;
public class DbConnection {
Connection dbConn = null;
public static Connection dbConnect(){
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection dbConn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=H:/Integ Ongoing Project/_Midterm Project/Server/src/database/Database.accdb");
return dbConn;
}catch(Exception e){
System.out.println(e.getMessage());
return null;
}
}
}
Password is a reserved word. If you must keep that as your field name, enclose it in brackets in your query to reduce the likelihood of confusing the database engine.
UPDATE Student
SET
lastname = ?,
firstname = ?,
course = ?,
yearlvl = ?,
username = ?,
[password] = ?
WHERE student_id = ?
Note I included a WHERE clause, as Stephen suggested, because it seems unlikely you would want those same field values applied to every row in the Student table. I used student_id as a placeholder name for the table's primary key ... the field which uniquely identifies each row. My intention is that you revise the WHERE clause to reference the primary key for the student whose record you want to alter.
If you're actually trying to add a new record, instead of update an existing record (or records), use an INSERT statement.
INSERT INTO Student (
lastname,
firstname,
course,
yearlvl,
username,
[password]
)
VALUES (
?,
?,
?,
?,
?,
?
)
And if you have autonumber as the data type of your primary key, the db engine will manage it for you.
I think that the problem is that your SQL statement is missing a WHERE clause. (I know that WHERE is optional in some dialects of SQL ... but a missing WHERE makes no sense to me here.)
The reason I think this is wrong is that even if the SQL dialect allows this, it is not clear which row of the table you are "setting". Even if the SQL engine can figure it out, a WHERE clause makes it a lot clearer. (And the fact that it "works" in the other case, doesn't mean that it is necessarily correct.)
Another thing that is potentially the cause of the problem is that "password" is a reserved word in some SQL dialects. Change the column name, or escape it.
Finally, the actual SQL error message should be in the exception stacktrace, or failing that in the log files. Those should be the first places to look if you are trying to find a problem in your database code. Look for the evidence ... rather than hoping someone else guess the right answer for you.

Java General Error On Insert...???

I am trying to do an Insert, Update and Delete on a table in MS Access. Everything works fine
for a SELECT statement. But when doing the other three operations, I don't seem to get any
errors, but the actions are not reflected on to the DB. Please help...
THe INSERT statement is as follows:
PreparedStatement ps = con.prepareStatement("INSERT INTO Student VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
ps.setInt(1,1);
ps.setString(2,"ish");
ps.setInt(3,100);
ps.setInt(4,100);
ps.setInt(5,100);
ps.setInt(6,300);
ps.setInt(7,100);
ps.setString(8,"A");
ps.executeUpdate();
Also may I know why PreparedStatement is used except for SELECT statement...
I get this error:
Exception in thread "main" java.sql.SQLException: General error
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6986)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(JdbcOdbc.java:3149)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(JdbcOdbcPreparedState
ment.java:216)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(JdbcOdbcPrepare
dStatement.java:138)
at Student.main(Student.java:19)
This is my code...
import java.sql.*;
import java.io.*;
class Student {
public static void main(String args[]) throws SQLException, IOException, ClassNotFoundException {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:Student","","");
Statement st = con.createStatement();
PreparedStatement ps = con.prepareStatement("INSERT INTO Student VALUES (?, ?, ?, ?,
?, ?, ?, ?)");
ps.setInt(1,1);
ps.setString(2,"Girish");
ps.setInt(3,100);
ps.setInt(4,100);
ps.setInt(5,100);
ps.setInt(6,300);
ps.setInt(7,100);
ps.setString(8,"A");
ps.executeUpdate();
con.commit();
con.close();
}
}
This can happen when you don't commit/close the connection. Ensure that you're committing the connection after executing the statement and are closing the connection (and statement and resultset) in the finally block of the try block where they are been acquired and executed.
As to why the PreparedStatement is used, it's the common approach to avoid SQL injection attacks and to ease setting fullworthy Java objects like Date, InputStream, etc in a SQL query without the need to convert them to String.
I believe your prepared statement is of the wrong format. The documentation for INSERT INTO (available here: http://msdn.microsoft.com/en-us/library/bb208861(v=office.12).aspx) gives this format:
Single-record append query:
INSERT INTO target [(field1[, field2[, …]])] VALUES (value1[, value2[, …])
You give the format:
INSERT INTO target VALUES (value1[, value2[, …])
edit:
To be more clear I believe you want something like:
PreparedStatement ps = con.prepareStatement("INSERT INTO Student (Year, Name, field3 ...) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
Where Year, Name, field3 ... are the names of the fields you are trying to insert into.
The main reason for using a PreparedStatement is security. Generating a SQL query by concating strings is unsafe as the variable parts may contain SQL statements entered by a user. This would allow to execute statements like DROP TABLE * to the user (see SQL Injection). Theres is is a good idea only to use PreparedStatemnts if the SQL query is not static (doe snot contain variable parts).
Therefore it would be better also to use PreparedStatement for SELECT statements.
Edit :
You try to Insert your Student Primary Key, if it's an Identity column, it will not work.
You need to prepare your statement like this :
PreparedStatement ps = con.prepareStatement("INSERT INTO Student(Field1,Field2,Field3,Field4,Field5,Field6,Field7) VALUES (?, ?, ?, ?, ?, ?, ?)");
Without your Primary Key set, the DB will do it for you.
.
.
.
Original post :
There is a kind of similar question on StackOverflow.
You won't see any result from INSERT queries with Access until you close your Connection properly.
Your code doesn't close any resources, which will surely bring you grief. Call the close methods (in reverse order if there are more than one) in a finally block.
Here is a class DataBaseUtils to help you if needed.
public class DatabaseUtils
{
public static Connection createConnection(String driver, String url, String username, String password)
throws ClassNotFoundException, SQLException
{
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
public static void close(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(Statement statement)
{
try
{
if (statement != null)
{
statement.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(ResultSet rs)
{
try
{
if (rs != null)
{
rs.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
}

Categories