Missing semicolons at line-end of JPA-generated sql script - java

I am using JPA to generate a script for creating database tables based on my entities:
javax.persistence.schema-generation.scripts.action=create
javax.persistence.schema-generation.scripts.create-target=db_setup.sql
The file is generated with the correct tables, however the statements do not end with a semicolon, for example:
create table hibernate_sequence (next_val bigint)
insert into hibernate_sequence values ( 1 )
insert into hibernate_sequence values ( 1 )
I assume this is valid in standard SQL? However, it is not valid in MySQL. Is there a way to tell JPA to add the semicolons to the end of the line? Or what else could be the reason that it is missing?

Since Hibernate 5.1.0, the line delimiter for the generated SQL can be defined by setting the hibernate.hbm2ddl.delimiter property, e.g.
hibernate.hbm2ddl.delimiter=";"
The default is no delimiter.
See also comments on this ticket.

Related

Query for the allowed values in a constraint

I want to extract values from a CHECK constraint on a database table. The code is:
CONSTRAINT Shop_check_serviceType CHECK (service_type IN ('food or drink', 'entertainment', 'retail'))
In Postgres 12 there is a column named consrc in pg_catalog.pg_constraint. But I use Postgres 14 and I don't know how to extract the values there. I have tried to search the manual without success.
Use the dedicated function pg_get_constraintdef() to reverse-engineer the SQL-DDL code of constraint definition.
SELECT pg_get_constraintdef(oid)
FROM pg_catalog.pg_constraint
WHERE contype = 'c' -- CHECK constraint
AND conrelid = 'public.my_table'::regclass -- your table name here
AND connname = 'shop_check_servicetype'; -- lower-cased?
If you did not double-quote the constraint name "Shop_check_serviceType" it has been converted to lower-case.
Related:
Delete rows with foreign key in PostgreSQL
BTW, the (redundant) column consrc existed up to Postgres 11 and had already been dropped from pg_catalog.pg_constraint in Postgres 12. pg_get_constraintdef() reproduces what used to be in that column.
Quoting the release notes of Postgres 12:
Remove obsolete pg_constraint.consrc column (Peter Eisentraut)
This column has been deprecated for a long time, because it did not
update in response to other catalog changes (such as column
renamings). The recommended way to get a text version of a check
constraint's expression from pg_constraint is pg_get_expr(conbin, conrelid). pg_get_constraintdef() is also a useful alternative.

Cannot apply Flyway migration for a PostgreSQL table

In my Java app, I have the following migration file:
-- code omitted for brevity
create table if not exists demo_table
(
id bigint not null,
"company" varchar(50) not null,
"name" varchar(50) not null
);
create unique index if not exists demo_table_uuid_company_key
on demo_table (uuid, "company");
create index if not exists demo_table_name_company_key
on demo_table ("name", "company");
Although I can run the sql part part part or at a time on PostgreSQL query window, when running my Java app, it throws the following error:
"Unable to create index (name, company) on table demo_table: database column 'name' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"
I tried many thing e.g. removing the related migration row from flyway_schema_history table, delete indexes on demo_table, etc. But still the same error. If I try to remove double quotes ("") from name, it gives checksum error. So, as the name is reserve word, I use with double quotes. How can I fix it?
On the other hand, I am not sure if I should change these parameters on application.yml:
spring:
flyway:
enabled: true
jpa:
hibernate:
ddl-auto: update
Some minor issues with the script:
Missing comma on first column of create.
This column is also called id but the index references uuid.
Resolving this allowed the script to work perfectly for me (with the quotes as you have them)
If you make these changes and get a checksum error, please run flyway repair

How can I get an id for a new record in a generic way? (JOOQ 3.4 with Postgres)

With jooq 3.4 I can't figure out how to do this (with Postgresql):
Query query = dsl.insertInto(TABLE)
.set(TABLE.ID, Sequences.TABLE_ID_SEQ.nextval());
but in a case when I don't know which is the exact table, something like this:
TableImpl<?> tableImpl;
Query query = dsl.insertInto(tableImpl)
.set(tableImpl.getIdentity(), tableImpl.getIdentity().getSequence().nextval());
Is it somehow possible?
I tried this:
dsl.insertInto(tableImpl)
.set(DSL.field("id"),
tableImpl.getSchema().getSequence("table_id_seq").nextval())
This works but I still don't know how to get the sequence name from the TableImpl object.
Is there a solution for this? Or is there a problem with my approach?
In plain SQL I would do this:
insert into table_A (id) VALUES nextval('table_A_id_seq');
insert into table_B (table_A_id, some_val) VALUES (currval('table_A_id_seq'), some_val);
So I need the value or a reference to that id for later use of the id that was generated for the inserted record as default, but I don't want to set any other values.
jOOQ currently doesn't have any means of associating a table with its implicitly used sequence for the identity column. The reason for this is that the sequence is generated when the table is created, but it isn't formally connected to that table.
Usually, you don't have to explicitly set the serial value of a column in a PostgreSQL database. It is generated automatically on insert. In terms of DDL, this means:
CREATE TABLE tablename (
colname SERIAL
);
is equivalent to specifying:
CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
The above is taken from:
http://www.postgresql.org/docs/9.3/static/datatype-numeric.html#DATATYPE-SERIAL
In other words, just leave out the ID values from the INSERT statements.
"Empty" INSERT statements
Note that if you want to create an "empty" INSERT statement, i.e. a statement where you pass no values at all, generating a new column with a generated ID, you can use the DEFAULT VALUES clause.
With SQL
INSERT INTO tablename DEFAULT VALUES
With jOOQ
DSL.using(configuration)
.insertInto(TABLENAME)
.defaultValues()
.execute();
Returning IDs
Note that PostgreSQL has native support for an INSERT .. RETURNING clause, which is also supported by jOOQ:
With SQL
INSERT INTO tablename (...) VALUES (...) RETURNING ID
With jOOQ
DSL.using(configuration)
.insertInto(TABLENAME, ...)
.values(...)
.returning(TABLENAME.ID)
.fetchOne();

MySQL + JAVA - Can't insert a table into another

I can't seem to insert my old table into the new table. Very weird
Code:
INSERT INTO 'newhawk_playewadwds' (`player_id`,'player') SELECT `player_id`,'player' FROM 'hawk_playewadwds';
Error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You
have an error in your SQL syntax; check the manual that corresponds to your MySQ
L server version for the right syntax to use near ''newhawk_playewadwds' (`playe
r_id`,'player') SELECT `player_id`,'player' FROM 'h' at line 1
Extra info:
Both tables exist and have slightly diffrent column structors (One has a varchar(50), while the other doesn't). Which is why i included the direct columns in the statement.
Quotes are delimiters for strings. Use backticks to escape column and table names, not quotes.
INSERT INTO `newhawk_playewadwds` (`player_id`,`player`)
SELECT `player_id`,`player`
FROM `hawk_playewadwds`;
But you actually only need to escape the reserved words.
Try to replace ' char with table names and for column player as below
INSERT INTO `newhawk_playewadwds` (`player_id`,`player`)
SELECT `player_id`,`player`
FROM `hawk_playewadwds`;
Use backticks across the query. You are using backticks and single quotes. Either use backticks or remove the single quotes:
-- This will work (Backticks only)
INSERT INTO `newhawk_playewadwds` (`player_id`,`player`)
SELECT `player_id`,`player`
FROM `hawk_playewadwds`;
-- This will also work (No backticks and no single quotes)
INSERT INTO newhawk_playewadwds (player_id,player)
SELECT player_id,player
FROM hawk_playewadwds;
Another thing, as you mentioned column structures are different,
If newhawk_playewadwds has column > 50, and hawk_playewadwds has < 50, It shouldn't be a problem
If hawk_playewadwds' has > 50 andnewhawk_playewadwds` has <50, then do either of the following:
Increase the size of the new table newhawk_playewadwds to same size of hawk_playewadwds
Use Substring in select as:
INSERT INTO `newhawk_playewadwds` (`player_id`,`player`)
SELECT `player_id`,SUBSTRING(`player` ,1,50)
FROM `hawk_playewadwds`;

hibernate inserting without left ticks

I am trying to do insert using hibernate and am running into an issue. When I use the following code
#Override
public Serializable addTestResult(Result test_result) {
// TODO Auto-generated method stub
return getCurrentSession().save(test_result);
}
the end query looks like this:
mysql> insert into test_results (db, host) values ('db1', 'host1');
which gets rejected by mysql since there are left tick missing in the column name. How can I have hibernate add quotes around the column name so that the query looks like this:
mysql> insert into test_results (`db`, `host`) values ('db1', 'host1');
Quote the table/ column names you need quoted with ` back-ticks in your .hbm.xml or mapping annotations.
For example:
<property name='DB" column='`db`' />
#Column(name="`db`")
This tells Hibernate to quote these identifiers to the database. I use this, for example, with a `USER` table. As with any app, most table & column-names are not conflicting but user tends to be a SQL keyword.
You don't need to switch on quoting globally.
Try to add the option hibernate.globally_quoted_identifiers=true.
Source: Automatic reserved word escaping for Hibernate tables and columns

Categories