In my aplication I use eclipselink and the criteria api.
My database have a table with a column called "order".
The problem is when I use the criteria api to create a select it made this sql:
SELECT id, order, name, phone, uri FROM campus
It throw a exception because "order" is a restrict keyword in sql
How can I force the criteria api to put quotes in the columns names?
The easiest (and IMHO the best) way is to change order to campus_order or something like that and avoid using SQL keywords as a field identifier. This practice typically causes problems.
I will be glad to know that criteria API has some kind of work around for this problem but I'd recommend you to rename the column. Today you are using criteria API, tomorrow you will use something else... But at the end of the day the good old SQL is generated and the last think you want is to find that one of your queries does not work because the column name equals to keyword of one of SQL versions.
Renaming the field is an easier option, but JPA will quote delimited fields. To mark it as delimited, just add quotes when defining the column: "\"order\"".
Related
What is the safe way how to put table name as parameter into SQL query? You cannot put table name as parameter using PreparedStatement. Concatenating string to execute query with dynamic table name using Statement is possible, however it is not recommended because of risk of SQL injection. What is the best approach to do this?
The best way would be:
To put your table name between the characters used to delimit the name of the table which change from one database to another
And escape the provided table name accordingly such that SQL injection won't be possible anymore.
So for example in case of MySQL, the table name's delimiter is the backquote character and we escape it by simply doubling it.
If your query is SELECT foo from bar, you could rewrite your query as next:
String query = String.format("SELECT foo from `%s`", tableName.replace("`", "``"));
This way you inject the name of your table without taking the risk of seeing some malicious code being injected.
I would try to solve the design problem, so you don't have to set the table name dynamically. If this is not possible, I would go for a design where you manage a list of available tables and users pick one from there, BY ID, so you can retrieve the real table name from the chosen id and replace the table name placeholder with it, avoiding any chance of sql injection in the table name replacement.
There is a rationale behind allowing only actual parameters in dynamic JDBC queries: the parameters can come from the outside and could take any value, whereas the table and column names are static.
There can be use cases for parameterizing a table or a column name, mainly when different tables have almost same structure and due to the DRY principle you do not want to repeat several times the same query only changing the table (or column) name. But in that use case, the programmer has full control on the names that will substituted, and should carefully test that there is no typo in any of them => there is no possibility of SQL injection here, and it is safe to replace the table name in the query string.
That is quite different for a web application exposed on internet where a query will use what has been entered in a form field, because here anything could occur, including a semicolumn to terminate the original harmless query and forge a new harmfull one => SQL injection if you just concatenate strings instead of correctly building a parameterized query.
I cannot imagine a use case where the table name or a column name could be a string typed in a form field by a user, which would be the only reason to allow to parameterize them.
Im using google app engine data-store built in eclipse using my model for the table. The id is just the date and time from android.
I can query by a row like this and it does work!
select from Quotes as Quotes ORDER BY votes DESC
I want to get my results back by my entities id however this query does not work
select from Quotes as Quotes ORDER BY Id DESC
Here is my table. How can I query by my id/Name and trust me ive tried
select from Quotes as Quotes ORDER BY ID/Name DESC
edit: you probably notice i have a dummyid. I do not want to use that row because I made it in a very hacky way and requires extra loading on the users side.
Oh, dear. I see the problem, now. You have a column named ID/Name. It's usually wise to keep identifiers limited to alphanumeric characters.
Can you rename the column? That would be the best step forward.
If that's not an option, you can wrap it in backticks so that it's treated as an identifier:
SELECT * FROM Quotes ORDER BY `ID/Name` DESC;
See SQL Fiddle, which almost certainly won't match your schema but should get the point across.
That Id/Name is the key field, imagine it is similar to primary key. to refer to that field in query, use
__key__
Example: select * from EntityTable where __key__ = Key('EntityTable', ....)
In your example, using date/time as key name is not really helpful, maybe you can find another info to be used as key.
Each table in my database have these fixed columns:
record_version
record_timestamp
create_time
Thanks to jooq feature record_version and record_timestamp are automatically handled.
Is it possible to centralize and automate the maintenance of create_time ?
Internally jooq is already managing the first two special fields.
Can I put a handler somewhere to fill the create_time value?
Doing so, I could remove some boilerplate code to initialize this field.
I have another field on each table: update_by_account; anyway If I'm able to manage the previous mentioned field (create_time) I think I'll handle this field too.
thanks in advance
Future jOOQ versions:
What you're looking for is the Listener API feature for Record and UpdatableRecord. It has not yet been implemented as of jOOQ 3.0
In the future, this feature will allow to inject some behaviour to jOOQ's records, when they are stored, inserted, updated, deleted, etc. This would include what you are requesting as well as what jOOQ is currently doing with its
record_version
record_timestamp
columns used for optimistic locking.
A solution for jOOQ 2.x or 3.0:
What you can do right now is implement an ExecuteListener and let it "detect" if it should become active and override a bind value for create_time. This will probably have to resort to parsing or at least regex-matching your SQL statement.
A SQL-only solution:
However, the best option for create_time, in my opinion, is to write a trigger for every one of your tables (Oracle syntax):
CREATE OR REPLACE TRIGGER my_trigger
BEFORE INSERT
ON my_table
REFERENCING NEW AS new
FOR EACH ROW
BEGIN
:new.create_time = SYSDATE;
END t_triggers_trigger;
This will guarantee that the value is available no matter how you access your database...
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).
I am taking a 'Keyword' and table name from user.
Now, I want to find all the columns of table whose data type is varchar(String).
Then I will create query which will compare the keyword with those column and matching rows will be returned as result set.
I tried desc table_name query, but it didn't work.
Can we write describe table query in JPQL?
If not then is there any other way to solve above situation?
Please help and thank you in advance.
No workaround is necessary, because it's not a drawback of the technology. It is not JPQL that needs to be changed, it's your choice of technology. In JPQL you cannot even select data from a table. You select from classes, and these can be mapped to multiple tables at once, resulting in SQL joins for simplest queries. Describing such a join would be meaningless. And even if you could describe a table, you do not use names of columns in JPQL, but properties of objects. Describing tables in JPQL makes no sense.
JPQL is meant for querying objects, not tables. Also, it is meant for static work (where classes are mapped to relations once and for good) and not for dynamic things like mapping tables to objects on-the-fly or live inspection of database (that is what ror's AR is for). Dynamic discovery of properties is not a part of that.
Depending on what you really want to achieve (we only know what you are trying to do, that's different) you have two basic choices:
if you are trying to write a piece of software in a dynamic way, so that it adjusts itself to changes in schema - drop JPQL (or any other ORM). Java classes are meant to be static, you can't really map them to dynamic tables (or grow new attributes). Use rowsets, they work fine and they will let you use SQL;
if you are building a clever library that can be shared by many projects and so has to work with many different static mappings, use reflection API to find properties of objects that you query for. Names of columns in the table will not help you anyway, since in JPQL queries you have to use names defined in mappings.
Map the database dictionary tables and read the required data from them. For Oracle database you will need to select from these three tables: user_tab_comments, user_tab_cols, user_col_comments; to achieve the full functionality of the describe statement.
There are some talks over the community about dynamic definition of the persistent unit in the future releases of JPA: http://www.oracle.com/goto/newsletters/javadev/0111/blogs_sun_devoxx.html?msgid=3-3156674507
According to me, we can not use describe query in jpql.