Having a Column name as Input Parameter of a PreparedStatement - java

I already used the search here (and other forums as well) but haven't found an answer exacty to what I'm trying to do.
I know that it can easily be done in some other way, and this is just a small sandbox-framework I'm coding for a University course... in a real environment I'd just take Spring, Hibernate etc.
So what I did was coding myself a small generic Data Access Layer with POJOs, working with generic methods to retrieve, check or insert data to the database (Oracle). Most of this is done through PreparedStatements.
This is working as long as I don't have joins... is it possible to put in a Column as parameter?
Example:
Table A has Attribute X + others
Table B has Attribute Y + others
PreparedStatement with query SELECT * FROM A,B WHERE "A"."X" = ?
And then fill in "B"."Y" as the parameter...
The database doesn't throw me an error or exception, but the ResultSet returned after executing the statement is empty. Is it just not possible to do, or am I just missing some escaping?
I'm using PreparedStatement.setString(int index, String value) to fill in the parameter... in lack of ideas which other setX method I could use...
Again, in a real project I'd never code that myself, but rather use something like Spring or Hibernate and not re-invent the wheel, but I see it as an interesting exercise to code such a generic small data access layer myself.

No, JDBC does not allow this. Only column values can be set. If you want to make dynamic changes to the sql statement you will have to do it before you create the PreparedStatement.

Related

Remediating dynamic SQL into prepared statements

I am starting a remediation of dynamic SQL statements to prevent SQL injection. I have a Web UI that uses more than 50 queries. I would like to write a Java class to build the set statements without knowing the primitive type ahead of time that way it could be more generic? I was hoping there was a class I could call that I do not know about? I have searched for answer but I am sure I am searching wrong.
(i.e. prepStatement.setInt(1,999); prepStatement.setString(2,”Sammy”) ; etc. )
If I understand the question correctly, you want to dynamically construct PreparedStatement objects at runtime, without knowing parameter types in those statements, probably so that you code can work with different tables?
From that I conclude that you need to find out the column data types and call appropriate PreparedStatement.set* methods.
Leaving aside how your code will receive table name, and parameter values for prepared statement, you can obtain column information by calling Connection.getMetaData().getColumns(...). For every column, corresponding row in the ResultSet will contain a column DATA_TYPE with an int corresponding to one of the java.sql.Types.
The DatabaseMetaData interface has a lot of useful methods for getting details about a particular database.

Java JDBC: Why is it necessary to register out-parameter?

I've got to learn Java JDBC currently.
Today I had a look on how Stored Procedures are called from within JDBC.
What I don't get ..., when I have a Stored Procedure like for example this one:
CREATE PROCEDURE demo.get_count_for_department
(IN the_department VARCHAR(64), OUT the_count INT)
BEGIN
...
"the_count" is marked as an out parameter. Type is also specified. So this should all be known.
Nevertheless I have to specify the type again
statement.registerOutParameter(2, Types.INTEGER);
I have to put the type in there again? It seems redundant to me.
Why do I have to give two parameter in there at all?
statement = connection.prepareCall("{call get_count_for_department(?, ?)}");
I haven't seen this in any other programming language. You only have to take care for the in-parameter. For the out-parameter takes the function care itself.
Why is that different here?
Perhaps someone can drop me a few lines. So that I get a better idea about how those Stored Procedure-calls work.
The reason is that the sql statement is just a string as seen from java perspective.
The task of a JDBC driver is to send that string to the database and receive results.
You could read the stored procedure metadata to get information about the stored procedure you are about to call but that takes time and possibly multiple queries to the DB.
If you want that kind of integration you go a step up from JDBC and use some kind of utilities or framework to map DB object to java ones.
Depending on the database it might technically not be necessary. Doing this allows a JDBC driver to execute the stored procedure without first having to query the database for metadata about the statement, and it can also be used to disambiguate between multiple stored procedures with the same name (but different parameters).

How to group a result set into a list from SQL statement?

Suppose I want I have a SQL like select * from game;, but I want only one SQL to execute to group different games result into Java List.
Say we have game1, game2, game3 in the content of column 'game' in the resultset, so I need a List whose length is 3 and each element inside is a SQL ResultSet(if I can have a OR Mapping, that will be great) so that I can parse them later.
SpringFramework contains a class called JdbcTemplate which contains a method called query, this is will take a SQL statement with relevant parameters and return a List with your results but it will require some work to set it up. I think you're looking for something a bit more 'out of the box' which just does it in a single line, but I don't think this is possible. There are other methods in the class which do the same thing but take different parameters based on what you have available in your code.
See the JdbcTemplate api for more details if you're interested.

Using JOOQ just to store table/column names and types with no regard to Record types

I'm currently evaluating JOOQ because I believe I started reinventing the wheel which looks very close to part of JOOQ :)
Now, while digging in great JOOQ documentation I've found that my use case lies somewhere between Using JOOQ as SQL Builder and Using JOOQ as SQL Builder with Code generation i.e. I would like to:
Create plain SQL strings like it is shown in Using JOOQ as SQL Builder part
Instead of using hard-coded DSL.fieldByName("BOOK","TITLE") constructs, I prefer storing name of a table along with it's column names and types like it's shown in Using JOOQ as SQL Builder with Code generation part
I prefer not to use code generation (at least not on regular basis), but rather creating TableImpl myself when new table is needed.
While digging in manual, I've found how table implementation should look like in chapter Generated tables. However, TableImpl class as well as Table interface should be parameterized with record type and the same goes for TableField class. I believe this is done for easier type inference when directly querying database and retrieving results, though I may be mistaken.
So my questions are:
Is there a guide in manual on how to create Table and TableField implementations? Or I can simply generate them once for my database schema and use generated code as a guideline?
How can I gracefully "discard" record type parameters in implemented classes? First, I thought about using java.lang.Void class as type parameter but then I noticed that only subclasses of Record are allowed... The reason is that I don't need record types at all because I plan to use generated by JOOQ SQL queries in something like Spring JdbcTemplate so mapping is done by myself.
Thanks in advance for any help!
Given your use-case, I'm not sure why you'd like to roll your own Table and TableField implementations rather than using the ones generated by jOOQ. As you stated yourself, you don't have to regenerate that code every time the DB schema changes. Many users will just generate the schema once in a while and then put the generated artefacts under version control. This will help you keep track of newly added changes.
To answer your questions:
Yes, there are some examples around the use of CustomTable. You may also find some people sharing similar experiences on the user group
Yes you can just use Record. Your minimal custom table type would then be:
class X extends TableImpl<Record> {
public X() {
super("x");
}
}
Note that you will be using jOOQ's internal API (TableImpl), which is not officially supported. While I'm positive that it'll work, it might break in the future, e.g. as the super constructor signature might change.

Connecting Java Object with MySql Tables

I am working with Java Classes, and I'm looking for the easiest way to connect a DB table in MySQL with the members (attributes) to the Java code.
After executing the "SELECT" query I get a resultSet, yet it is not clear to me how to cast the result Object to the Java Object generically.
For Example: I have 2 Java Classes - Student & Teacher, and I would like to use a command:
Student student = (Student) rs.getObject();
Thanks,
Roi
I would recommend using JPA with eclipselink implementation, rathern than executing queries using plain JDBC, and try to map results from resultsets to objects by hand (error prone). JPA will do that for you !
this doesn't work in that way. You should do something like:
Student st = new Student();
st.setName(rs.getString("NAME"));
st.setAverage(rs.getInt("SCORE"));
where NAME and SCORE are the column names.
The doc can also help you.
You can look at ORM solutions, like Hibernate.
If your question is about rs.getObject.
The call rs.getObject is a generic way of calling rs.getInt, rs.getString because the return values of all these methods are ultimately Objects (Int, String etc...).
It will return the column you ask for (either by order number in the select or by column name). Not the whole bean corresponding to a row.
You use rs.getObject when you do not know at compilation time the type of the returned column.
The JDBC ResultSet Object does not have a magic getObject method that will return the bean corresponding to a select statement.
You can develop your own 'poor man's ORM' with combination of
JBBC ResultSetMetaData
Java Reflexion
But that's a harder work than using an existing one.

Categories