I'm having a problem with my ORMLite package. When I generate the schema for a table, I thought it would be a good practice to escape all entity names. This would protect some Java class or field name from being a SQL reserved word:
CREATE TABLE "footable" ("stuff" VARCHAR(255))
I'm now adding "raw" query support so that ORMLite can help users perform their own queries. However, I find that with Derby and Hsqldb, the entity names cannot be used without escaping. For example, the following query:
SELECT * FROM footable
generates the following errors:
Derby: ERROR 42X05: Table/View 'FOOTABLE' does not exist.
Hsqldb: Table not found in statement [select * from footable]
It works fine if the select table is also escaped as "footable". The other databases supported by ORMLite work fine with or without the escaping: MySQL, Postgres, Microsoft SQL Server, H2, and Sqlite.
Are there better ways to escape reserved words in Derby and Hsqldb? Other ideas about how to do this in a portable manner?
Thanks.
So kudos to Bryan for leading me down the path although his answer wasn't quite right.
Turns out that because I am creating the database as "footable" then, as Bryan states, it will be create case sensitively. However, when I did the select on footable (without quotes) Derby and Hsqldb are promoting it to be all uppercase so I'm in effect doing:
SELECT * FROM FOOTABLE
It's not about being case insensitive without the quotes (which would have worked) but about promoting the entity names to be all capitals when there are no quotes and then matching by case. I'd argue there was a bug here...
In any case, I've changed my Derby and Hsqldb to capitalize all entity names in ORMLite and things are working. Ugly IMO, but working.
You just have to make sure that the case matches.
So if it's:
create table "Footable" ("Stuff" varchar (25))
Then it has to be:
insert into "Footable" ("Stuff") values 'hi mom'
If the table/column name is in double quotes, the case is preserved as is.
If the table/column name is not in double quotes, then Derby handles it insensitive to case.
Related
It seems PostgreSQL does not allow to create a database table named 'user'. But MySQL will allow to create such a table.
Is that because it is a key word? But Hibernate cannot identify any issue (even if we set the PostgreSQLDialect).
user is a reserved word and it's usually not a good idea use reserved words for identifiers (tables, columns).
If you insist on doing that you have to put the table name in double quotes:
create table "user" (...);
But then you always need to use double quotes when referencing the table. Additionally the table name is then case-sensitive. "user" is a different table name than "User".
If you want to save yourself a lot of trouble use a different name. users, user_account, ...
More details on quoted identifiers can be found in the manual: http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
It is possible to specify tablename with JPA with next syntax:
#Table(name="\"user\"")
We had this same issue time ago, and we just changed the table name from user to app_user. Due to the use of Hibernate/JPA. We thought it would be easier this way.
Hope this little fix will help someone else.
You can create a table user in a schema other than public.
The example:
CREATE SCHEMA my_schema;
CREATE TABLE my_schema.user(...);
Trailing underscore
The SQL standard explicitly promises to never use a trailing underscore in any keyword or reserved word.
So, to avoid conflicts with any of the over a thousand keywords and reserved words used by various database engines, I name all my database identifiers with a trailing underscore. (Yes, really, over a thousand keywords reserved — I counted them.)
Change this:
CREATE TABLE user ( … ) ;
… to this:
CREATE TABLE user_ ( … ) ;
I do this as a habit for all database names: schemas, tables, columns, indexes, etc.
As an extra benefit, this practice makes quite clear in documentation, email, and such when referring to a programming language variable named user versus the database column user_. Anything with a trailing underscore is obviously from the database side.
How to compose SQL(MySQL) like PreparedStatement, such as escaping, to avoid SQL injection and genearte safe SQL statement.
Is there any present JavaCode to do this?
Real scenario:
Frontend input as column value to compose a safe SQL (the "where" part), the specified in the backend are table name and column name.
There are some SQL builders, and in general they keep track of all parameters and build a PreparedStatement. It might even be an idea to not only provide parameter values, but parameter names, so one may use it as a real PreparedStatement.
You may create a JdbcTemplate from Spring. Or Criteria API.
If you want to build your own, as research, you might explore escaping too.
Then (research) also consider barring Unicode bidi hacking with LTR (\u200E) and RTL (\u200F): by using a Right-To-Left control one can obfuscate the SQL looking seemingly okay in the editor, but doing something maliciously different. You could require that the characters may not appear in a string but must be escaped too: \\u200F. (However it is something for nerds or insiders, and your SQL must already be at a sensitive spot.)
The SQL dialect is important; backtick (MySQL) or double quotes (Standard) for names etcetera.
There is Apache's commonlang escapeSql.
I have a problem with a lower and upper function in JPA (Hibernate). In my application a user should add a new item to the database, but the name should be unique. In order to achieve that, I need to compare user entered string with the strings in the database and ignore case while checking that.
Unfortunately, as I am using the Hibernate function to make all data upper-cased (in order to compare that) everything works fine except for the Polish special characters that remain the same.
This is the code I've used for testing purposes in order to check if it works:
TypedQuery<String> query = em.createQuery("SELECT upper(i.name) FROM Item i", String.class);
for (String name: query.getResultList())
System.out.println(name);
And that's what I get:
CZYSTY BANDAż
MAłY CHEMIK
MAłY MECHANIK
SPRZęT
ŚPIWóR
ŚRODEK DEZYNFEKUJąCY
ŚRODEK CZYSZCZąCY
All letters should be upper-cased. In the database every first letter of a first word is always capitalized. The problem concerns such characters like: ą, ę, ż, ź, ó, ł - they should look like Ą, Ę, Ż, Ź, Ó, Ł, but Hibernate seems not to recognize them as a single character which differs only in regard to the case.
The same thing happens when I use a lower function. Polish characters are not affected at all and remain the same.
I do not know if it concerns only Polish characters or from any other languages too.
I would be very grateful for any hint in this matter.
EDIT: I'm using Hibernate 5.2.2 Final with SQLite database and driver Xerial 3.8.11.2.
EDIT2: The same happens if I try to achieve that using native SQL query with Hibernate.
I've already found the solution. It turned out, that SQLite doesn't support the Unicode collation. It can only support ASCII latin characters while using lower, upper function or sorting.
There is an extension (SQLite ICU Extension), that SQLite must be compiled with in order to use Unicode collation (or other collations), but as far as I'm concerned it is not as simple solution as I would like it to be. I've decided to change the database provider to H2, which support Unicode collation by default without performing any modifications and it works like a charm now :)
So it's not Hibernate's fault, but the SQLite's. Thank you very much for your help :)
I have a table name Order and since it is a reserved word in Hibernate, it is not letting me to construct desired query. Is there any way by which I can escape table name in HQL?
I got across similar question asking for alias How to escape reserved words in Hibernate's HQL
But this solution is not working for me. Is there any other way by which we can do this? I am using version 4.3 of hibernate.
Have you mapped the table to an entity that is also called Order? If so then I'd suggest renaming the entity as there as the Hibernate team appear to have rejected the request to add keyword escaping to HQL. If the problem is actually with the generated SQL then you can add backticks to the table name to escape it according to the database dialect that is in use.
I have a table with properties defined like this :
#Column(name="\"SERIAL#\"")
When Hibernate inserts data, everything works fine.
But it comes to Hibernate-Envers(HE), HE forgets to surround the field name with doublequotes.
How can i force it to use the doublequotes aroud the fields ?
Do you want to use double quotes, or do you want to escape the name? If you just want to escape, use backticks (`) and Hibernate will convert it to whatever mechanism your database uses for escaping. So, your example would be:
#Column(name="`SERIAL#`")
Just out of curiosity: why do you need a # in a column name? I always thought that special chars are a bad idea in identifiers :-)
For solving the problem, i manage to not use the '#' in the field name thus neither Hibernate nor Hibernate Envers have to escape the field name.
EDIT:
In fact it's a bug in Hibernate Envers 3.6.2.Final. It should be solved later.
EDIT 2:
The bug has been fixed in Hibernate Envers 3.6.3 and Hibernate Envers 4.0.0Alpha.
EDIT 3:
The bug has been fixed in Hibernate Core 3.6.4.Final.