I'm using Postgres via Hibernate (annotations), but it seems to be falling over dealing with a User object:
12:09:16,442 ERROR [SchemaExport] Unsuccessful: create table User (id bigserial not null, password varchar(255), username varchar(255), primary key (id))
12:09:16,442 ERROR [SchemaExport] ERROR: syntax error at or near "User"
If I run the SQL manually I have to put quotes around the table name as user seems to be a postgres keyword, but how can I convince hibernate to do this itself?
Thanks in advance.
You need to escape the table name when using reserved keywords. In JPA 1.0, there is no standardized way and the Hibernate specific solution is to use backticks:
#Entity
#Table(name="`User`")
public class User {
...
}
In JPA 2.0, the standardized syntax looks like this:
#Entity
#Table(name="\"User\"")
public class User {
...
}
References
Hibernate Core documentation
5.4. SQL quoted identifiers
JPA 2.0 specification
2.13 Naming of Database Objects
User is a key word, find a better name or use quotes: "User". (bad idea imho, but it works if you do it everywhere)
Related
I'm using Hibernate to create SQLite tables.
I have a table as such
#Entity
class Person(
#Column(unique = true, nullable = false)
val name: String,
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int? = null,
)
I see that when the database is created, the unique constraint is added later on via an ALTER request
Hibernate: create table Person (id integer, name varchar(255) not null, primary key (id))
Hibernate: alter table Person add constraint UK_is4vd0f6kw9sw4dxyie5cy9fa unique (name)
Except that SQLite does not seem to support ALTER requests modifying constraints on tables.
So my question is : Is there a way to literally indicate Hibernate to set that uniqueness constraint on table creation? What would be the best way to do it?
I can ensure uniqueness easily later on via code, but I'd rather use the power of the database if I can.
I should add that this is for a personal small application so so far I'm using the update setting for hibernate.hbm2ddl.auto so Hibernate generates the SQL itself. I'm open to other methods but I'd rather avoid them if I can to reduce maintenance.
Gonna answer my own question given that it's not getting much traction :).
SQLite indeed does not support ALTER with constraints, and Hibernate does not (to my knowledge) offer a clean way to use custom SQL.
On top of this, it is not recommended to use Hibernate: hbm2ddl.auto=update in production.
For those reasons, I decided to turn myself to Flyway and write my own SQL. The good news is that adding Flyway provides my database migrations. The bad news is that it's one more dependency to maintain.
What I've done:
Added the flyway dependency in my build.gradle.kts
implementation("org.flywaydb:flyway-core:8.4.3")
Instantiated flyway before hibernate in my code, pointing to the same database:
val flyway = Flyway
.configure()
.dataSource("jdbc:sqlite:test.db", null, null).load()
flyway.migrate()
Added a handwritten SQL migration file in resources/V1__Create_person_and_entries_table.sql
create table Person
(
id integer primary key,
name varchar(255) not null UNIQUE
);
Et voilà!
I wrote a blog post over here with more details and some more reasons to use something like Flyway.
i have spring boot application that uses my database schema. Lets say i have non-empty schema with table APPLICATION_USERS defined as follows:
create table AREA
(
name NVARCHAR2(36) not null,
id NUMBER not null
)
now i wanted to add FlyWay to my application. I have defined in my application properties flyway.baselineOnMigrate=true to start initial Flyway deployment and spring.jpa.hibernate.ddl-auto=validate to validate my Enities agains schema, however upon starting application i get following error:
wrong column type encountered in column [name] in table [APPLICATION_USERS]; found [nvarchar2 (Types#OTHER)], but expecting [varchar2(255 char) (Types#VARCHAR)]
as far as i understand it, it complains about NVARCHAR2, as it expect varchar how can i force hibernate to accept nvarchar2 as varchar?
i know i can use columnDefinition on my entity attributes, however this is not my dream solution, is there any other way?
I assume that you are using Oracle database.
You have to annotate your the attribute name in your Entity with Nationalized
#Nationalized
private String name;
You also could register your own dialect:
public class CustomOracleDialect extends Oracle10gDialect {
public CustomOracleDialect() {
super();
registerColumnType(Types.NVARCHAR, "nvarchar2($l)");
registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName());
}
}
I have the following jpa/hibernate/hsqldb configuration:
JPA ddl-auto: create-drop
Hibernate entities have no #Table annotation and created with SpringPhysicalNamingStrategy. So, PersonalData entity table name is personal_data. Hibernate creates them due to running the application
hsql DB URL is jdbc:hsqldb:mem:testdb;sql.syntax_pgs=true
My problem is when I try to select due spring repositories with the hsql there is the error about non-existing PERSONAL_DATA table.
I found that this is SQL notation to use CASE_SENSETIVE tables and hqsl follows that. To resolve that developers offer quote table names in sql.
So, I have 2 unlikely ideas
Add #Table annotation to entities.
Override SpringPhysicalNamingStrategy
Is there a way to use a simple property?
I am generating MySQL table by Hibernate as follows:-
#Entity
#Table(name = "buyerPartyDetails")
public class BuyerPartyDetails {
.......
}
But in MySQL the actual table name is as buyerpartydetails I was expecting it should be buyerPartyDetails. How do I force hibernte to genarate table name as my espection?
You can force Hibernate to quote the identifiers by setting:
hibernate.globally_quoted_identifiers=true
or
hibernate.globally_quoted_identifiers_skip_column_definitions=true
which will generate quoted table names in DDL. It might however require SET GLOBAL SQL_MODE=ANSI_QUOTES; as by default MySQL uses backticks ` to quote the names.
Env: JPA 1, Hibernate 3.3.x, MySQL 5.x
We auto generate database schema using hbm2ddl export operation. Would it be possible to generate a default value for a certain #Entity member during SQL generation. (e.g. archive field in mytable entity class.
create table mytable (
...
'archive‘ tinyint(1) default ’0 ’,
...
)
There is no portable way to do that and the columnDefinition "trick" is definitely not a good solution. Actually, setting defaults in the generated DDL is just not a good idea, this would require the provider to go back to the database to see the result after an insert1. Better default in your Java code.
1 Just in case, note that you can tell Hibernate to do that using the #Generated annotation.