Spring jdbc bug? - java

I'm using MySQL database and have written some procedures. If I try to create these procedures with spring jdbc I get error messages that these procedures already exist. If I connect the old fashion way with DriverManager create a PreparedStatement and execute it everything works just fine.
Does anyone know why this is happening?
here in code what I am doing
...
connection = new JdbcTemplate(dataSource);
...
for(String sql: sqlScript.split( "(;)" ) ){
connection.execute(sql.trim());
}
this results in SQL-Exception that the procedure I give as parameter already exists. But if I exchange the preceding code snippet against this:
for(final String sql: sqlScript.split( "(;/)" ) ) {
if (sql.trim().length() > 0)
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?"
+ "user=root" );
PreparedStatement ps =
conn.prepareCall(sql);
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
everything works fine...
Would be nice if anyone knows whats wrong here...
at least one of my procedures that already exists... probably even in your database...
create procedure insertUser(
in p_firstname varchar(50),
in p_lastname varchar(50),
in p_username varchar(25)
)
begin
declare l_username varchar(25);
select username into l_username
from movielist.user where username = p_username;
if l_username is null then
insert into movielist.User (firstname, lastname, username) values
(p_firstname, p_lastname, p_username);
end if;
end;/

Related

updating mysql db using java program

I am trying to add a new row in my table inside mysql db , i tried to use executeUpdate(); and executeQuery(); but both did not work, I am taking columns values from multiple JTextField and adding every one of them to a single Librarian object and then i call setLibrarian() method in main.
But I get the following error message:
java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '#gmail.com , 14 , cairo , 4.6565486E7 )' at line 1
here is my code:
public static void setLibrarian(Librarian lib){
Connection con = null;
Statement st = null;
String dbURL = "jdbc:mysql://localhost:3306/universitysystem";
String username = "root";
String password = "";
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(dbURL , username , password);
st = (Statement) con.createStatement();
st.executeUpdate("INSERT INTO librarians(username , password , email , address , city , contactno)"
+ " VALUES("+lib.getName()+" , "+lib.getPassword()+" , "+lib.getEmail()+" , "+lib.getAddress()+" , "+lib.getCity()+" , "+lib.getContactNo()+" ); ");
con.close(); //closing connection
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
catch(SQLException e){
e.printStackTrace();
}
}
You have a security leak, you must never put user input into a query statement like this. What if someone enters as password:
thisIsMyPassword'; DROP TABLE librarians CASCADE; EXECUTE 'FORMAT C: /force'; --
You'd be quite screwed.
The proper answer is PreparedStatement, which lets you write a single constant as a query (INSERT INTO librarians(...) VALUES (?, ?, ?, ?) - with the question marks) and then provide the value for each question mark separately, and then you're safe from the above issue (then that will simply be their password, verbatim).
This, in passing, also fixes your problem here, which is either that the double isn't working out, or more likely that there are ' symbols in that gmail address.
While you're at it, look at 'try with resources java', because the way you are closing your connections isn't safe either and results in memory leaks. Finally, exception handling with e.printStackTrace() is broken. Fix your IDE; the proper 'I do not care' content is throw new RuntimeException("Uncaught", e); - what you are doing results in many errors and code in unknown states (also a security issue).

Calling Oracle Stored Procedure from Java Web application

I am trying to call several oracle stored procedures from my web application. There are no in or out parameters in any of the procedures. Everything works perfectly when I run my web app locally, but when I deploy the app to our test server the stored procedure calls stop working. I get no error messages and the procedure does not run.
I would think it has something to do with the JDBC driver or connection, but I'm at a loss? Any help would be greatly appreciated!
Here is the code that works perfectly when running locally and debugging:
public boolean deleteFromTempTables(String id)
{
String msg = "";
CallableStatement stmt1 = null;
try
{
conn = DBConnection.getConnection();
DbmsOutput dbmsOutput = new DbmsOutput( conn );
dbmsOutput.enable( 1000000 );
stmt1 = conn.prepareCall("{call delete_from_temp_employee()}");
stmt1.execute();
stmt1.close();
dbmsOutput.show(id);
dbmsOutput.close();
}
catch(Exception e)
{
e.printStackTrace();
return true;
}
finally
{
try
{
stmt1.close();
conn.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
return false;
}
Here is the stored procedure:
create or replace procedure delete_from_temp_employee as
temp_empe_before NUMBER;
temp_empe_after NUMBER;
begin
select count(*) into temp_empe_before from temp_employee;
delete from temp_employee;
select count(*) into temp_empe_after from temp_employee;
DBMS_OUTPUT.PUT_LINE ('Procedure DELETE_FROM_TEMP_EMPLOYEE Employee Before: ' || temp_empe_before);
DBMS_OUTPUT.PUT_LINE ('Procedure DELETE_FROM_TEMP_EMPLOYEE Employee After: ' || temp_empe_after);
end delete_from_temp_employee;
Call in JSP page:
<%
boolean isDeleteError = false;
isDeleteError = memberupload.deleteFromTempTables(userid);
%>
you need to execute:
set serveroutput ON;
this command makes output works.
also after delete statement add commit; command to commit changes if you forget it.
by the way, you can get the affected rows for DML statements like delete statement by using sql%rowcownt as following:
set serveroutput ON;
create or replace procedure delete_from_temp_employee2 as
rows NUMBER;
begin
delete from temp_employee;
rows := SQL%rowcount;
DBMS_OUTPUT.PUT_LINE ('Deleted: ' || rows || ' row(s)');
end delete_from_temp_employee2;

java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended for INSERT INTO SELECT

I have a below query, which needs to select a row by using a column as key and return generated keys.
INSERT INTO t_tpms_cc_request
(process_identifier,
request_source_id,
amount,
etc_account_id,
retry_count,
status,
store_identifier,
version_no,
next_process_time,
composite_transaction_id,
payment_id,
processed_time,
replenishment_id,
pay_type,
agency_id,
response_code,
file_id,
request_date,
auth_file_id,
auth_date_time,
merc_file_id,
merc_date_time,
cc_num,
cc_expiration_date,
merchant_id,
ext_sys_ref,
encrypt_cc_number,
cc_month_cd,
cc_year_cd,
orig_txn_ref,
auth_code,
avs_code,
cvv_code)
SELECT CC.process_identifier,
CC.request_source_id,
CC.amount,
CC.etc_account_id,
CC.retry_count,
CC.status,
CC.store_identifier,
CC.version_no,
CC.next_process_time,
CC.composite_transaction_id,
CC.payment_id,
CC.processed_time,
CC.replenishment_id,
CC.pay_type,
CC.agency_id,
CC.response_code,
CC.file_id,
CC.request_date,
CC.auth_file_id,
CC.auth_date_time,
CC.merc_file_id,
CC.merc_date_time,
CC.cc_num,
CC.cc_expiration_date,
CC.merchant_id,
CC.ext_sys_ref,
CC.encrypt_cc_number,
CC.cc_month_cd,
CC.cc_year_cd,
CC.orig_txn_ref,
CC.auth_code,
CC.avs_code,
CC.cvv_code
FROM t_tpms_cc_request CC
WHERE CC.order_id = ?
And, I have wrriten a below java code to do this:
String key[] = {"order_id"};
DataSource ds = null;
Connection con = null;
ResultSet rs = null;
try {
ds = jdbcTemplate.getDataSource();
con = ds.getConnection();
PreparedStatement ps =
con.prepareStatement(insertCCRequest.trim(), key);
ps.setString(1, OrderId);
int i= ps.executeUpdate();
rs = ps.getGeneratedKeys();
if (rs.next()) {
return rs.getString(1);
}
} catch (SQLException e) {
logger.debug("SQL exception in RebillDao.insertCCrequest()
method..!! ");
logger.debug("Exception cause: "+e.getMessage());
e.printStackTrace();
throw e;
}
finally {
if(con!=null){
con.close();
}
}
return "";
When i run this, I get below exception:
java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended
Please tell me the ways to fix this.
Also, Using JDk 1.6 and ojdbc6-11.2.0.4.jar
I suspect that when you use generated keys with a prepared statement, the Oracle JDBC driver adds the RETURNING INTO clause to the INSERT statement, and that the JDBC driver is too dim to realise that the RETURNING INTO clause can't be used with INSERT INTO ... SELECT ... statements. I get the same ORA-00933 error if I attempt to run an INSERT INTO ... SELECT ... RETURNING ... statement.
What you could try instead is a PL/SQL block where we fetch the 'old' row into a record and then use an INSERT ... VALUES statement with a RETURNING_INTO clause to insert the values into the 'new' row:
DECLARE
l_row t_tpms_cc_request%ROWTYPE;
BEGIN
SELECT * INTO l_row FROM t_tpms_cc_request WHERE order_id = ?;
INSERT INTO t_tpms_cc_request (some_column, some_other_column, ...)
VALUES (l_row.some_column, l_row.some_other_column, ...)
RETURNING order_id INTO ?;
END;
As we're returning values from this, we need to prepare this as a CallableStatement instead of a PreparedStatement, and we need to register parameter 2 as an out parameter. We can then use this out parameter, instead of the getGeneratedKeys() method you're using at the moment, to return the generated key value.
Clearly this approach is Oracle-specific and won't work on other databases. I don't know how much of an issue database portability is to you, nor whether you can return generated keys from an INSERT INTO ... SELECT ... statement in other databases.

Proper use of Stored Procedure using Select

I created a Stored Procedure where I can select the column that I address in my Stored Procedure via Callable Statement. I tried to use SELECT SECTION NAME FROM allsections_list WHERE SECTION_NAME = ? Similar to syntax of Prepared Statement but I think its not compatible using this syntax. I'm just new learning this mysql.
Stored Procedure
CREATE STORED PROCEDURE getSECTION_NAME(OUT SECTION_NAME VARCHAR)
SELECT SECTION_NAME FROM allsections_list
Code
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
String searchSection = Section_SearchSection_Textfield.getText();
String searchSection_Name = Section_SectionName_TextField.getText();
if (searchSection.isEmpty())
{
JOptionPane.showMessageDialog(null, "Please fill up this fields");
}
else
try (Connection myConn = DBUtil.connect();
CallableStatement myCs = myConn.prepareCall("{call getSECTION_NAME(?)}"))
{
myCs.setString(1, searchSection_Name);
try (ResultSet myRs = myCs.executeQuery())
{
int resultsCounter = 0;
while (myRs.next())
{
String getSection_Name = myRs.getString(1);
Section_SectionName_TextField.setText(getSection_Name);
resultsCounter++;
}
}
}
catch (SQLException e)
{
DBUtil.processException(e);
}
When I search a records. If the records exist it the value will print out to the textfields. But it doesn't print out. And it throws me a error getSECTION_NAME does not exist. What if I want select multiple values? Because I'm having a project where I'm making a Enrollment System. I choose this Stored Procedure specially than Batch Statement based on what I read. Any help will appreciate. Thanks!
I don't use MySql, but here's a similar example in Oracle (I think this Works in MySql as well).
CREATE PROCEDURE get_section_name(OUT secName VARCHAR(100))
BEGIN
SELECT SECTION_NAME INTO secName FROM allsections_list WHERE some_condition = 100; //your procedure does not use any input arguments if you want to return just one record then you'll probably need to specify a where clause
END
/ //when executing a stored procedure in a DB client you will need to specify a terminator character (in this case slash /)
Note that there's no return statement because we're using OUT parameters.
The getOutValueForStoredProcedure method calls the stored procedure and retrieves the out value.
public String getOutValueForStoredProcedure(String procedureName, int sqlType) throws EasyORMException{
String out=null;
CallableStatement stmt=null;
try{
//out parameters must me marked with question marks just as input parameters
sqlQuery = "{call " + procedureName +"(?)}";
stmt=conn.prepareCall(sqlQuery);//I assume that a Connection has been created
stmt.registerOutParameter(1, sqlType);
stmt.execute();
out = stmt.getString(1);//you get the out variable through the Statement, not the ResultSet
}catch(Exception e){
//log exception
}finally{
//close stmt
}
return out;
}
To call this stored procedure, you can use
String out = getOutValueForStoredProcedure("get_section_name", java.sql.Types.VARCHAR);
For creating stored procedures in MySql , check this link http://code.tutsplus.com/articles/an-introduction-to-stored-procedures-in-mysql-5--net-17843
For a more elaborate example, check this http://www.mkyong.com/jdbc/jdbc-callablestatement-stored-procedure-out-parameter-example/

h2 getGeneratedKeys throws exception

I try to put some Data in my H2 database but I'm a total noob in databases so it throws error over error since more than a hour.
Normaly I can fix it somehow but now I got a new problem I try to use
getGeneratedKeys() first I tried to use AUTO_INCREMENT(1,1) but that didn't works too function but it won't work rigth.
The exception my programm throws is
org.h2.jdbc.JdbcSQLException: Funktion "GETGENERATEDKEYS" nicht gefunden
Function "GETGENERATEDKEYS" not found; SQL statement:
insert into logTbl values( getGeneratedKeys(),Webservice->startThread0: Thread0) [90022-173]
an my database function looks like this
public void createTable(String Log) {
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
System.err.println("TREIBER FEHLER");
e.printStackTrace();
}
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:h2:~/DBtest/Logs");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE IF NOT EXISTS logTbl(ID INT PRIMARY KEY, LOG VARCHAR(255))");
//stat.execute("insert into test values(1, 'Hello')");
for (int i = 0; i < 20; i++) {
stat.execute("insert into logTbl values( getGeneratedKeys()," + Log + ")");
}
stat.close();
conn.close();
} catch (SQLException e) {
System.err.println("SQL FEHLER");
e.printStackTrace();
}
}
hope you can help me to fix my error as I said I'm totaly new and just had some code example as "tutorial" because I don't found a good tutorial
If you want to automatically generate primary key values, you need to first change the definition of your table:
CREATE TABLE IF NOT EXISTS logTbl
(
ID integer AUTO_INCREMENT PRIMARY KEY,
LOG VARCHAR(255)
);
You should also use a PreparedStatement rather than concatenating values.
So your Java code would look something like this:
String insert = "insert into logTbl (log) values(?)";
PreparedStatement pstmt = connection.prepareStatement(insert, Statement.RETURN_GENERATED_KEYS);
pstmt.executeUpdate();
ResultSet rs = pstmt.getGeneratedKeys();
long id = -1;
while (rs.next())
{
rs.getLong(1);
}
It might be that you need to use the overloaded version of prepareStatement() where you supply the column to be returned. Not sure which one works with H2:
prepareStatement(insert, new String[] {"ID"});
Btw: there is nothing "magic" about 255 as the length of a varchar column. There is no performance difference between varchar(500), varchar(20)or varchar(255). You should use the length that you expect you need, not some "magic" limit you think performs better.

Categories

Resources