accessing HSQLDB table from JUnit not possible - java

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.

Related

One to one relationship Error on Postgresql

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);"

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 update a foreign key column?

I have below tables:
create table TABLE1 ( id int(10) unsigned NOT NULL AUTO_INCREMENT, deptId int(11) NOT NULL, DeptName varchar(32) NOT NULL, PRIMARY KEY (id), KEY Dept (deptId, DeptName))
create table TABLE2 ( id int(10) unsigned NOT NULL AUTO_INCREMENT, empId int(11) NOT NULL, DeptName varchar(32) NOT NULL, PRIMARY KEY (id), KEY DeptName (DeptName), CONSTRAINT T2FK FOREIGN KEY (DeptName) REFERENCES TABLE1 (DeptName))
TABLE1 has a MUL key defined with both dept id and dept name.
TABLE2 has a Foreign key which references only Dept name from TABLE1
The DTO for TABLE2 gets created like below:
#org.hibernate.annotations.NotFound(action = org.hibernate.annotations.NotFoundAction.IGNORE)
#javax.persistence.ManyToOne(targetEntity = org.amru.persistence.dto.TABLE1DTOImpl.class, fetch=javax.persistence.FetchType.EAGER)
#javax.persistence.JoinColumn(name = "deptName")
public org.amru.persistence.dto.TABLE1DTO getTABLE1() {
return TABLE1;
}
When I try to insert a row in TABLE2, it fails with foreign key constraint violation exception.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`amru`.`TABLE2`, CONSTRAINT `T2FK` FOREIGN KEY (`DeptName`) REFERENCES `TABLE1` (`DeptName`))
I also see a EntityExistsException when I debug
What is possibly wrong? Is it recommended to refer a part of MUL key as foreign key in another table?
I am using jpa, hibernate, jboss, ejb and mysql
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot add or update a child row: a foreign key constraint fails
What is possibly wrong?
This is very clear that, DeptName is foreign key in TABLE2, which is referring from TABLE1. So, you are not allowed to change the value in parent table as the data is being referenced in other table.
If you are supposed to do this, then you need to alter your table to apply cascade changes to child table as well for your Foreign Key
FOREIGN KEY (DeptName) REFERENCES TABLE1 (DeptName) ON DELETE CASCADE ON UPDATE CASCADE

Hibernate cannot rebuild tables due to broken foreign keys

Alright so, I have a Spring Boot application (1.5.2.RELEASE) that uses Hibernate (5.0.12.Final) and I'm having a few problems with Hibernate being unable to properly re-create my database on startup.
I configured Hibernate to create the tables again on startup:
spring.jpa.hibernate.ddl-auto=create
Here is my first entity (Client):
#Entity
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
private String name;
#NotNull
private String firstName;
#Email
#NotNull
private String email;
#Valid
#Embedded
private Credentials credentials = new Credentials();
#OneToMany(mappedBy = "client")
private List<Reservation> reservations = new ArrayList<>();
//Getters, Setters, hashcode & equals omitted
}
Reservation entity:
#Entity
public class Reservation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
private Client client;
#Enumerated(EnumType.STRING)
private State state = State.UNTREATED;
//Getters, Setters, hashcode & equals omitted
}
Here's an overview of the created database:
Here's the console output, I tried to abbreviate it for simplicity's sake:
INFO : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
INFO : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
INFO : HHH000227: Running hbm2ddl schema export
Hibernate: alter table reservation drop foreign key FKoewar6f18rkn4iptr6da4oysv
ERROR : HHH000389: Unsuccessful: alter table reservation drop foreign key FKoewar6f18rkn4iptr6da4oysv
ERROR : Can't DROP 'FKoewar6f18rkn4iptr6da4oysv'; check that column/key exists
Hibernate: drop table if exists client
ERROR : HHH000389: Unsuccessful: drop table if exists client
ERROR : Cannot delete or update a parent row: a foreign key constraint fails
Hibernate: drop table if exists reservation
Hibernate: drop table if exists restaurant
Hibernate: create table client (id bigint not null auto_increment, created_on datetime, credentials_version integer not null, hash varchar(255), username varchar(255), email varchar(255) not null, first_name varchar(255) not null, name varchar(255) not null, primary key (id))
ERROR : HHH000389: Unsuccessful: create table client (id bigint not null auto_increment, created_on datetime, credentials_version integer not null, hash varchar(255), username varchar(255), email varchar(255) not null, first_name varchar(255) not null, name varchar(255) not null, primary key (id))
ERROR : Table 'client' already exists
Hibernate: create table reservation (id bigint not null auto_increment, state varchar(255), client_id bigint, primary key (id))
Hibernate: create table restaurant (id bigint not null auto_increment, primary key (id))
Hibernate: alter table reservation add constraint FKoewar6f18rkn4iptr6da4oysv foreign key (client_id) references client (id)
INFO : HHH000230: Schema export complete
INFO : Initialized JPA EntityManagerFactory for persistence unit 'default'
INFO : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
INFO : HHH000227: Running hbm2ddl schema export
ERROR : HHH000389: Unsuccessful: alter table `Reservation` drop foreign key `FK8gjvlt7rp8i9kp7rdmn107ni7`
ERROR : Can't DROP 'FK8gjvlt7rp8i9kp7rdmn107ni7'; check that column/key exists
ERROR : HHH000389: Unsuccessful: drop table if exists `Client`
ERROR : Cannot delete or update a parent row: a foreign key constraint fails
ERROR : HHH000389: Unsuccessful: create table `Client` (`id` bigint not null auto_increment, `createdOn` datetime, `credentialsVersion` integer not null, `hash` varchar(255), `username` varchar(255), `email` varchar(255) not null, `firstName` varchar(255) not null, `name` varchar(255) not null, primary key (`id`))
ERROR : Table 'client' already exists
INFO : HHH000230: Schema export complete
I don't know if it matters but the MySQL database version is 5.7.13 running on Windows. Also I didn't include the Restaurant entity and the Credentials embeddable.
I find it strange that Hibernate is trying to drop a foreign key that doesn't exist first and then drop the right one and both fail (if I'm reading it correctly).
What is the reasoning/cause behind this? And how to prevent these issues?
I've looked at other relevant SO questions and they are usually caused by invalid names or simmilar but I don't see anything wrong with my naming. I've also tried prefixing all my tables with "tbl_" and renaming some columns with a prefix as well just in case something was causing a conflict but no luck.
It's bothering me because the database is not updating properly and during active development I don't want to drop/create schema manually every time. Maybe it's worth mentioning that, even if the schema is empty, on startup, hibernate will give errors that things don't exist.
Try it. I think issue in Reservation
#ManyToOne
#JoinColumn(name = "client_id")
private Client client;
Firstly, you should understand how foreign key constraint names are generated:
How does hibernate generate foreign key constraint names?
So, if you change table or foreign key column names, you will have a different foreign key constraint name and Hibernate will not be able to delete the old foreign key constraint.
What you can do:
Specify a foreign constraint name using
#javax.persistence.ForeignKey annotation (don't confuse it with
#org.hibernate.annotations.ForeignKey, although it can be used
to).
Use spring.jpa.hibernate.ddl-auto = update to just update schema,
not to recreate it every time.
Use a naming strategy to generate foreign key names (working with Hibernate 5 only). But you will need to think how to combine table, associated table, columns names to have not often foreign constraint name change: Need help in implementing ImplicitNamingStrategy for foreign key column names in Hibernate 5

SQL Foreign Key Error using Hibernate POJOs

We have the following situation:
We use Java's Hibernate to write POJO-Classes to a database.
The classes are annotated as follow:
#Entity
#Table(name = "dbo.SaveEvents")
We get the following error when writing to the database (Table: dbo.CodeDocuments)
WARN: SQL Error: 547, SQLState: 23000
Feb 06, 2017 2:06:42 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_SaveEvents_CodeDocuments". The conflict occurred in database "OSBLEPlus_eclipse", table "dbo.CodeDocuments", column 'Id'.
org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112)
We tried to satisfy the Foreign Key constraint by adding:
#SecondaryTable(name = "dbo.CodeDocuments")
But this doesn’t solve our problem. We also didn’t find a lot about how to use the SecondaryTable annotation properly. The mapping FK <-> PK is as follows:
CodeDocuments.sql:
CREATE TABLE [dbo].[CodeDocuments] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[FileName] VARCHAR (MAX) NOT NULL,
[Content] VARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_CodeDocuments_Id] PRIMARY KEY CLUSTERED ([Id] ASC)
);
SaveEvents.sql:
CREATE TABLE [dbo].[SaveEvents] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[EventLogId] INT NOT NULL,
[EventDate] DATETIME NOT NULL,
[SolutionName] VARCHAR (MAX) NOT NULL,
[DocumentId] INT NOT NULL,
CONSTRAINT [PK_SaveEvents] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_SaveEvents_EventLogs] FOREIGN KEY ([EventLogId]) REFERENCES [dbo].[EventLogs] ([Id]),
CONSTRAINT [FK_SaveEvents_CodeDocuments] FOREIGN KEY ([DocumentId]) REFERENCES [dbo].[CodeDocuments] ([Id])
);
How would one go about inserting into 2 tables at once using Hibernate POJOs aka fixing the foreign key error?
You simply need to make sure you persist your CodeDocument entity first folllowed by the associated SaveEvents entities:
CodeDocument codeDocument = new CodeDocument();
// set the values
session.save( codeDocument );
SaveEvents saveEvents = new SaveEvents();
// set the values
saveEvents.setDocument( codeDocument );
session.save( saveEvents );
Hope that helps.

Categories

Resources