No value specified for parameter 1 - java

I am using Hiberante to connect to postgres database. I am trying to insert a record into the database. I have the values for the record in a string array which I got from a csv file. This is my dao code
StringBuffer query=new StringBuffer("insert into t_wonlist values(");
for(int i=0;i<67;i++){
query.append(values[i]+",");
}
query.deleteCharAt(query.lastIndexOf(","));
query.append(");");
sessionfactory.getCurrentSession().createSQLQuery(query.toString()).executeUpdate();
System.out.println("Query executed");
sessionfactory.getCurrentSession().flush();
I am using StringBuffer, so that I can append the values into the query using a for loop.
but when I execute the query I am getting the following exception
org.postgresql.util.PSQLException: No value specified for parameter 1.
I am sure that the number of parameters is correct. Can someone help me. Thanks

You're approaching this in a bizarre and backwards manner.
The immediate problem is probably failure to escape/quote a ? in one of the input strings, so PgJDBC thinks it's a query parameter. That doesn't mean you should fix it by escaping/quoting question marks, it's a sign you're taking entirely the wrong approach.
Please read this page on SQL injection and this site.
You're using the Hibernate ORM, so you'd usually be using the JPA interface or the direct Hibernate interface to create new domain objects and persisting them. The typical approach is to new an object, then use the EntityManager.persist method (if using JPA) or the Session.save method (if using Hibernate directly) to persist the entities.
If you want to use direct JDBC instead you should be creating a JDBC PreparedStatement, setting its parameters, and then applying it. See this tutorial. Since you're loading CSV you'd usually do this in a JDBC batch, though this doesn't actually gain you much in PostgreSQL.
Better yet, since you're importing CSV you can probably just use PostgreSQL's built-in COPY command via PgJDBC's CopyManager to stream the changes efficiently into the target table.

Related

Can I pass table name as argument to a java prepared statement?

I am writing a DAO layer IN Java for my Tomcat server application,
I wish to use Prepared Statement wrapping my queries (1. parsing queries once, 2. defend against SQL injections),
My db design contains a MyISAM table per data source system. And most of the queries through DBO are selects using different table names as arguments.
Some of this tables may be created on the fly.
I already went though many posts that explain that i may not use table name as an argument for Prepared statement.
I have found solutions that suggest to use some type of function (e.g. mysql_real_escape_string) that may process this argument and append the result as a string to the query,
Is there any built in Jave library function that may do it in the best optimized way, or may be you may suggest to do something else in the DAO layer (i do not prefer to add any routines to the DB it self)?
Are you able to apply restrictions to the table names? That may well be easier than quoting. For example, if you could say that all table names had to match a regex of [0-9A-Za-z_]+ then I don't think you'd need any quoting. If you need spaces, you could probably get away with always using `table name` - but again, without worrying about "full" quoting.
Restricting what's available is often a lot simpler than handling all the possibilities :)
If you want to be extra safe than you can prepare a query and call it with supplied table name to check if it really exists:
PreparedStatement ps = conn.prepareStatement("SHOW TABLES WHERE tables = ?");
ps.setString(1, nameToCheck);
if(!ps.executeQuery().next())
throw new RuntimeException("Illegal table name: " + nameToCheck);
(The WHERE condition might need some correction because I don't have mysql under my fingers at the moment).

Cannot use bind variables in a DDL statement. Alternatives?

first of all, a preface: I'm writing a java class that creates temporary tables on a database using jdbc. I'm using JSE6 and Oracle 11XE as a test DB, but the class needs to be also DB2 compliant.
The temporary tables I'm trying to create come from a bigger one, and I do some filtering and aggregations on the data. The parameters I base my filtering on are decided by the user at runtime. One simplified example of what I'm trying to do is this:
CREATE TABLE temp_table AS (
SELECT
table1.department_id,
SUM(CASE WHEN table1.number_1 < &1 THEN table1.number_1 ELSE 0 END)) AS column1
FROM
table1
GROUP BY table1.department_id
)
My problem is that I need to specify parameters to filter the data, and I need to be sure they're properly escaped/localized/typed. This would be easy using a prepared statement, but I cannot use bind variables with DDL.
The temporary solution I resorted to is to alter the query String myself, writing the parameters in the correct place, but this means I now have to implement all the checks instead of relying on a PreparedStatement object to do it for me, on top of losing all the other benefits.
I investigated other solutions, but none of them convinced me so far:
I could first create an empty temp_table and then fill it with INSERT INTO temp_table(id, column1) (SELECT ...) but it seems I might incur in performance loss, so I'd like to stick to the CREATE temp_table AS
I thought about creating a temporary statement to hold the inner SELECT query, and have it generate a properly formatted/localized/etc. query string, but I haven't found any way to obtain the final query from it (and I read it's definitely not possible here). The only option I found for this case is to use DebuggableStatement, but I'm not sure I can include it in the project (also, it seems a quite inelegant way of solving my problem)
Another solution I'm thinking of, is to simply put the queries that create the temporary tables (for each of them I'd put the whole CREATE AS (SELECT...) on the database, inside a procedure, which I'll then be able to call using CallableStatement. this way I could avoid handling typization and still have good performances, at the price of a tighter coupling with the db (I'd have to be sure the procedures are there, or manage in java their addition/removal from the db)
So, my question is: are there better alternatives than the ones I could think of?
Is this supposed to be database agnostic, or are you targeting for only Oracle? You don't have to store PL/SQL in a stored procedure to use it; just build an anonymous PL/SQL block that does what you need, and execute it. The anonymous PL/SQL block can be built dynamically so that strongly typed variables are declared in the PL/SQL to hold your parameters, and then your java code sticks the values in. The type safety wouldn't be handled by Java since you're just building a string; it would be handled by Oracle when you execute the anonymous PL/SQL block.

Reading Multiple Resultset using JPA

I am using JPA(Eclipselink) to execute SQL Server Stored Procedure which returns multiple Resultsets.
As per my knowledge, easiest way to call a SP is:
entityManager.createNativeQuery("exec sp_name").getResultList();
After executing the SP I can only read the single (or very first) ResultSet.
Can some one please suggest how do I retrieve the next ResultSets (or ResultLists())?
I can't answer for EclipseLink specifically, and I'm not sure what the JPA spec says, but most features of JPA took their cue from Hibernate, and Hibernate's limitations on stored procedures are:
The procedure must return a result set. Note that since these servers can return multiple result sets and update counts, Hibernate will iterate the results and take the first result that is a result set as its return value. Everything else will be discarded.
My guess is that JPA defines the same limitation.
EclipseLink has extended support for stored procedures through its StoreProcedureCall class and NamedStoredProcedureCallQuery annotation. You can create a JPA Query using a StoredProcedureCall using the JpaEntityManager interface createQuery(Call) API.
StoreProcedureCall provides additional support over JPA native SQL queries including support for in, out and intout parameters and cursored output parameters and typing. StoreProcedureCall supports calls with both a result set and output parameters, but does not currently support multiple result sets.
What is being returned in your second result set, and how do you want the result returned? You could subclass and customize your SQLServerPlatform in EclipseLink and overwrite the executeStoredProcedure() method to process multiple results sets. It should not be to hard, and you could contribute the code back to EclipseLink if successful. Or you could log and enhancement request for this feature. Looking at the code it should be simple enough to implement, the bigger issue is how to return the multiple result sets.

Add description to columns using Java code

I can create a table and its columns in Java by using the statement:
CREATE TABLE table_name(column1 int, column2 double, etc...)
What I would like to do is to add descriptions to each of these columns with an appropriate statement, I found a stored procedure sp_addextendedproperty that looks like it can be used to accomplish this I just have no idea how to use it in java with jdbc.
Are you creating the table dynamically at runtime (e.g. as part of your application) - perhaps that's even user-driven? If that's the case, you already have that "documentation" (column comments) somewhere and I doubt the utility of adding them to SQL Server.
But if you're just trying to automate your build, take a look at LiquiBase. It's a pretty decent DB change management system that uses XML as backbone. It's written in java and integrates well with Hibernate (useful if you ever decide to use ORM instead of straight JDBC).
Update: If you do decide to go forward with calling stored procedure via JDBC, I would strongly recommend using CallableStatement to invoke it. Dynamically building SQL queries in the application should be avoided if possible.
There are a number of ways to call a stored procedure (essentially, preparing the statement and binding the variables, or sending a string of SQL), but the simplest is to just send rhe SQL statement
exec sp_addextendedproperty list, of, arguments, the, sp, needs;
Skipping your try/finally boilerplate, and assuming connection is a java.sql.Connection, that's:
connection
.createStatement()
.execute( "exec sp_addextendedproperty arguments;");
But ChssPly76 has a good point: doing this from Java isn't a good idea (unless you're developing some database manager in Java).

JDBC generation of SQL in PreparedStatement

I had a really huge problem recently which took me a lot of time to debug. I have an update statement which updates 32 columns in table. I did that with PreparedStatement. Accidentaly I deleted one setParameter() call so update could not be finished successfully.
I got exception from JDBC (Apache Derby) telling: "At leas one parameter is not initialized" and was not able to figure out which parameter is not set since driver would not tell you nothing about name or ordinal number of at least first parameter which is not set...
I was googleing unsuccessfully for some utility which will produce plain old SQL out of (nearly-finished) prepared statement. It would help a lot in situations like this one, since I will be able to see what is not set.
Have anyone faced this problem? Got any solution?
Have a look at P6Spy. It can intercept all your JDBC calls and log them before forwarding them onto your database.
Alternatively, think about using Springs JDBCTemplate which can take out alot of your boilerplate JDBC coding and help avoid these kind of mistakes. You don't need the rest of the Spring framework to use this bit.
Since the parameters in a prepared statement are just a List or Map in the PreparedStatement Object you should be able to inspect the values.
Also you could write a very simple Wrapper around you jdbc driver that creates wrapped PreparedStatements and logs all parameters and there settings before actually executing the statement.

Categories

Resources