One to one relationship Error on Postgresql - java

I would like to seek your insights regarding the error I'm encountering with my postgresql commands.
Basically, what I want to achieve is to create a "booking" entity with one to one relationship to another table called "booking details". But flyway won't migrate my schema with the following error:
Caused by: org.flywaydb.core.internal.sqlscript.FlywaySqlScriptException:
Migration V0__Initial.sql failed
--------------------------------
SQL State : 42S02
Error Code : 42102
Message : Table "BOOKING_DETAILS" not found; SQL statement:
ALTER TABLE booking ADD CONSTRAINT FK_BOOKING_ON_BOOKING_DETAILS FOREIGN KEY (booking_details_id) REFERENCES booking_details (booking_entity_id) [42102-214]
Line : 16
Statement : ALTER TABLE booking ADD CONSTRAINT FK_BOOKING_ON_BOOKING_DETAILS FOREIGN KEY (booking_details_id) REFERENCES booking_details (booking_entity_id)
Here is my postgresql commands:
DROP SEQUENCE IF EXISTS booking_transaction_sequence;
DROP TABLE IF EXISTS booking;
CREATE SEQUENCE IF NOT EXISTS booking_transaction_sequence START WITH 1000 INCREMENT BY 100;
CREATE TABLE booking (
id BIGINT NOT NULL,
booking_number VARCHAR(255),
booking_status VARCHAR(255),
processed_by VARCHAR(255),
created_at TIMESTAMP WITHOUT TIME ZONE,
booking_details_id BIGINT,
CONSTRAINT pk_booking PRIMARY KEY (id)
);
ALTER TABLE booking ADD CONSTRAINT FK_BOOKING_ON_BOOKING_DETAILS FOREIGN KEY (booking_details_id) REFERENCES booking_details (booking_entity_id);
DROP SEQUENCE IF EXISTS booking_details_transaction_sequence;
DROP TABLE IF EXISTS booking_details;
CREATE SEQUENCE IF NOT EXISTS booking_details_transaction_sequence START WITH 1000 INCREMENT BY 100;
CREATE TABLE booking_details (
booking_entity_id BIGINT NOT NULL,
sender_name VARCHAR(255),
item_details VARCHAR(255),
pickup_address VARCHAR(255),
rider_name VARCHAR(255),
delivery_address VARCHAR(255),
cancellation_reason VARCHAR(255),
CONSTRAINT pk_booking_details PRIMARY KEY (booking_entity_id)
);
ALTER TABLE booking_details ADD CONSTRAINT FK_BOOKING_DETAILS_ON_BOOKINGENTITY FOREIGN KEY (booking_entity_id) REFERENCES booking (id);
I would highly appreciate any inputs regarding this. Thank you.
I tried using the "extend" method on my BookingDetails entity to BookingEntity. This run my java springboot application but for some reason I can't fetch data with internal error 500 in postman. So I change my sql commands with the one-to-one relationship mapping but I got the above errors.

Just out of interest - how you're planning to insert new entries given the schema? In order to create booking you'd need to have booking_details created and vice versa.

The error message indicates that the table "BOOKING_DETAILS" is not found when you're trying to create a foreign key constraint in the "booking" table.
You need to make sure that the "booking_details" table is created before creating the foreign key constraint in the "booking" table. You can do this by reordering your migration script to create the "booking_details" table before creating the "booking" table with the foreign key constraint.
Additionally, check that the table name and column name used in the foreign key constraint statement are correct and match the names used in the "booking_details" table.

Solution: put this command on the last part of the sql so that the two tables must be created first before it can be altered.
"ALTER TABLE booking ADD CONSTRAINT FK_BOOKING_ON_BOOKING_DETAILS FOREIGN KEY (booking_details_id) REFERENCES booking_details (booking_entity_id);"

Related

Flyway and PostgreSQL nullable definition of foreign key still generates a non-null constraint

I use Spring Boot and Flyway with this initialization script:
CREATE TABLE ADDRESS(
ID bigserial NOT NULL PRIMARY KEY
);
CREATE TABLE ROLE(
ID bigserial NOT NULL PRIMARY KEY
);
CREATE TABLE PERSON(
ID bigserial NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(255),
LAST_NAME VARCHAR(255),
ADDRESS bigserial NOT NULL REFERENCES ADDRESS (ID),
ROLE bigserial REFERENCES ROLE (ID) -- notice here is no 'not null'
);
All the relationship between the tables is that:
Each PERSON has 0-1 ROLE. So, each ROLE belongs to 0-n PERSON. Hence, this relationship is nullable.
Each PERSON has 1 ADDRESS. So, each ADDRESS belongs to 1-n PERSON. Hence, this relationship is not-null.
As soon as I start the application (I have also tried to post the query straight to the PostgreSQL database schema), there is somehow generated constraint not-null between the PERSON and ROLE tables.
Using DataGrip, I select SQL Scripts -> Generate DDL to Query Console and get the DDL for the tables (see below, new lines and roles definitions omitted for sake of brevity).
To my surprise, the NOT NULL is there although I haven't defined such constraint. How to get rid of it aside from altering table?
create table if not exists address
(
id bigserial not null
constraint address_pkey primary key
);
create table if not exists role
(
id bigserial not nullconstraint role_pkey primary key
);
create table if not exists person
(
id bigserial not null
constraint person_pkey primary key,
first_name varchar(255),
last_name varchar(255),
address bigserial not null
constraint person_address_fkey references address,
role bigserial not null -- why is 'not null' here?
constraint person_role_fkey references role
);
The version of PostgreSQL I use (through SELECT version()) is:
PostgreSQL 10.13, compiled by Visual C++ build 1800, 64-bit
"8.1.4. Serial Types":
The data types smallserial, serial and bigserial are not true
types, but merely a notational convenience for creating unique
identifier columns (similar to the AUTO_INCREMENT property supported
by some other databases). In the current implementation, specifying:
CREATE TABLE tablename (
colname SERIAL
);
is equivalent to specifying:
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
Note the NOT NULL.
Don't use bigserial for the foreign key. That doesn't make much sense. Simply use bigint.
CREATE TABLE IF NOT EXISTS person
(...
role bigint REFERENCES role);
Possible solution 1:
Changing Biserial to Bigint does not remove the null constraint set to foreign key column when running flyway in springboot to write into postgres DB (at least for my case)
postgres:11.3-alphine 3.4
flyway: 8.0.5
To be secure, need to add scripts to alter columns to be nullable
ALTER TABLE mytable ALTER COLUMN mycolumn DROP NOT NULL;
Change Postgres column to nullable
Possible solition 2:
When Spring boot set JPA Hibernate ddl configuration to create, create-drop, update, flyway DB migration script will be updated by JPA entities properties. NOT NULL constraints can be added by JPA entities.
Change JPA Hibernate ddl configuration to none or validate will ensure only flyway script is used to create schema.
JPA Hibernate ddl configuration

How to put FK constraint on two tables in mysql with one table with InnoDB and other is MyISAM

Reason: liquibase.exception.JDBCException:
Error executing SQL ALTER TABLE `User` ADD CONSTRAINT `fk_user_location` FOREIGN KEY (`location_id`) REFERENCES `Location`(`id`) ON DELETE CASCADE:
Caused By: Error executing SQL ALTER TABLE `UserLocation` ADD CONSTRAINT `fk_user_location_location_id` FOREIGN KEY (`location_id`) REFERENCES `Location`(`id`) ON DELETE CASCADE:
Caused By: Can't create table 'usiapp_db.#sql-399a_177a7' (errno: 150)
You cannot. You have to convert your MyISAM table to InnoDB if you want create foreign keys to or from it:
ALTER TABLE MyIsamTable ENGINE=InnoDB;
You can do this dynamically, without taking down your database.

INSERT with DEFAULT id doesn't work in PostgreSQL

I tried running this statement in Postgres:
insert into field (id, name) values (DEFAULT, 'Me')
and I got this error:
ERROR: null value in column "id" violates not-null constraint
I ended up having to manually set the id. The problem with that is when my app inserts a record I get a duplicate key error. I am building a java app using Play framework and ebean ORM. So the entire schema is generated automatically by ebean. In this case, what is the best practice for inserting a record manually into my db?
Edit:
Here is how I'm creating my Field class
#Entity
public class Field {
#id
public Long id;
public String name;
}
Edit:
I checked the field_seq sequence and it looks like this:
CREATE SEQUENCE public.field_seq INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;
Edit:
Here is the generated SQL in pgAdmin III:
CREATE TABLE field
(
id bigint NOT NULL,
created timestamp without time zone,
modified timestamp without time zone,
name character varying(255),
enabled boolean,
auto_set boolean,
section character varying(17),
input_type character varying(8),
user_id bigint,
CONSTRAINT pk_field PRIMARY KEY (id),
CONSTRAINT fk_field_user_3 FOREIGN KEY (user_id)
REFERENCES account (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT ck_field_input_type CHECK (input_type::text = ANY (ARRAY['TEXT'::character varying, 'TEXTAREA'::character varying]::text[])),
CONSTRAINT ck_field_section CHECK (section::text = ANY (ARRAY['MAIN_CONTACT_INFO'::character varying, 'PARTICIPANT_INFO'::character varying]::text[]))
);
CREATE INDEX ix_field_user_3
ON field
USING btree
(user_id);
There is no column default defined for field.id. Since the sequence public.field_seq seems to exist already (but is not attached to field.id) you can fix it with:
ALTER SEQUENCE field_seq OWNED BY field.id;
ALTER TABLE field
ALTER COLUMN id SET DEFAULT (nextval('field_seq'::regclass));
Make sure the sequence isn't in use for something else, though.
It would be much simpler to create your table like this to begin with:
CREATE TABLE field
(
id bigserial PRIMARY KEY,
...
);
Details on serial or bigserial in the manual.
Not sure how the the Play framework implements this.
This works.
insert into field (id, name) values (nextval('field_seq'), "Me");

accessing HSQLDB table from JUnit not possible

I have the problem that my unit tests fails due to the fact that I can simply not access a table which has just been created before.
From the output of the console I can see that the following Hibernate commands are executed.
Hibernate: alter table Server_Node drop constraint FK3621657E1249AF15
Hibernate: alter table Server_Node drop constraint FK3621657E2528B004
Hibernate: drop table EmailAccountSettings if exists
Hibernate: drop table Node if exists
Hibernate: drop table Server if exists
Hibernate: drop table Server_Node if exists
Hibernate: create table EmailAccountSettings (id varchar(255) generated by default as identity (start with 1), description varchar(255), name varchar(255), primary key (id))
Hibernate: create table Node (id bigint generated by default as identity (start with 1), name varchar(255), primary key (id), unique (name))
Hibernate: create table Server (id integer generated by default as identity (start with 1), name varchar(255), primary key (id), unique (name))
Hibernate: create table Server_Node (Server_id integer not null, nodes_id bigint not null, primary key (Server_id, nodes_id))
Hibernate: alter table Server_Node add constraint FK3621657E1249AF15 foreign key (nodes_id) references Node
Hibernate: alter table Server_Node add constraint FK3621657E2528B004 foreign key (Server_id) references Server
Hibernate: insert into Server (id, name) values (default, ?)
As you can see values get inserted into the table Server. But the next test case is trying to insert something into table EmailAccountSettings which is causing the following error.
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: EMAILACCOUNTSETTINGS
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Any idea what is wrong with the table EmailAccountSettings?
I'm using Spring + Hibernate + HSQLDB + JUnit just to give an overview over the components involved.
Found the reason for this problem. Looking again at the table creation statement all of a sudden the light came on.
Hibernate: create table EmailAccountSettings (id varchar(255) generated by default as identity (start with 1), description varchar(255), name varchar(255), primary key (id))
It is not possible to create an identity column with datatype varchar. Therefore the statement was not successful. But this is not visible in the console when running the test.
After changing the datatype in the entity everything works as expected.

Entity class with DB showing Table with No primary key

I want to create an Entity class with database in Netbeans.
When I select a Data source jdbc/Ionbank (custom Jdbc connection Using JDBC-ODBC bridge with Ms SQL 2005 as database).
I see all the tables from that database.
All tables show no primary key, but they have primary keys in them.
Things I have tried :-
Created new 4-5 data source.
Created tables using query, and not the New table option.
Tried changing Odbc connection.
Tried using different drivers for the Jdbc-Odbc bridge like Sql4jdbc.jar, Jdts.jar.
I had same issue, but i solved it using the following: "New Entity Classes from Database" cannot process some tables, saying "no primary key"
A quote from that link helped me:
The problem will happen if you have foreign keys where upper case and lower case table names don't match the referenced table's definition.
For instance:
create table OkTable (
id int not null auto_increment
, primary key (id)
);
create table MisunderstoodTable(
id int not null auto_increment
oktable int not null
, primary key (id)
, foreign key ok (oktable) references oktable (id)
);
The MisunderstoodTable has a foreign key where the target table name doesn't match the lower/uppercase name of the referenced table.
To avoid this problem, just make sure you type your foreign key definitions while matching upper/lower casing for the targeted table.

Categories

Resources