Why does Hibernate/Spring generate foreign key on ID field. Causes foreign key volation - spring

I am new to Hibernate/Spring and am having an issue with autogenerated foreign keys and constrain violation. I have the following class properties:
#Id
#Column(name="MEDICATION_ID", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private long medicationId;
#Column(name="PATIENT_ID")
private long patientId;
private long dosageMg; // dose for patient in mgs
private long active; // active = 1, inactive = 0
private String medicationName; // name, oxy, etc.
private String medicationCode; // global identifier for this medications
private long activeDate;
private long inactiveDate;
When I start my server I notice that it generates the following code foreign key on the medicationID
Hibernate: alter table medication add constraint FK_dbfuno3knrhmabosmfty7l3ta foreign key (all_medications_MEDICATION_ID) references medication
Then when it tries to execute this insert statement from my import.sql it throws a constraint violation error.
delete from medication;
insert into medication (medication_id, patient_id, dosage_mg, active, medication_name, medication_code, active_date,inactive_date ) values (1000, 101, 10, 1, 'Oxy', 'oxy_10', 10000, 50000);
The error reads:
Caused by: org.hsqldb.HsqlException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10127 table: MEDICATION column: ALL_MEDICATIONS_MEDICATION_ID
Any ideas on why this foreign key was generated and how I can get around this constraint violation.
Thanks!

Related

Get list of database errors on saveAll()

I have a CountryObject:
#Entity
#Table(name = "country")
class CountryObject(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
val id: Long? = null,
#Column(name = "name")
val name: String,
#Column(name = "ISO2", length = 2)
val ISO2: String,
#Column(name = "ISO3", length = 3)
val ISO3: String
) : Serializable
with the corresponding PostgreSQL create script that has some unique constraints on ISO2 and ISO3:
CREATE TABLE country
(
id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
iso2 VARCHAR(2) NOT NULL,
iso3 VARCHAR(3) NOT NULL,
CONSTRAINT pk_country PRIMARY KEY (id)
);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO2 UNIQUE (iso2);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO3 UNIQUE (iso3);
Along with this I have a corresponding repository:
#Repository
interface CountryRepository : JpaRepository<CountryObject, Long>
And out of the box implementation of the CountryRepository has a saveAll() method that tries to insert a list of objects into the country table. So far, everything behaves as expected.
Once I try to insert a list that have multiple objects violating the unique constraints, the exception is thrown on the first and stopped. What I want to have is to get some list with the errors that I can use as a report, which mentions which entries failed saving. Of course nothing should be saved in that case and the transaction is rolled back.
Any hints how something like this can me achieved? Of course one option would be to try to save each object separately and then collect the errors, but that might be not that performant.

Cannot get many to many relationship in spring bootstrap

I have a very simple many to many scenario: One ORDER has many PRODUCT, and each product can belong to many orders.
order :
#Entity
#Table(name = "ORDER")
public class OrderEntity {
#Id
#Column(name="ORDER_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="ORDER_NAME")
private String name;
#Column(name="ORDER_DATE")
private Date date;
#ManyToMany
private List<ProductEntity> selectedProducts = new ArrayList<>();
product:
#Entity
#Table(name = "PRODUCT")
public class ProductEntity {
#Id
#Column(name="PRODUCT_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="PRODUCT_NAME")
private String name;
#Column(name="PRODUCT_PRICE")
private BigDecimal price;
#ManyToMany
private List<OrderEntity> orders = new ArrayList<>();
(removed getters and setters and constructors for brevity)
However when I startup bootstrap then I get a whole host of errors :
Error executing DDL "drop table order if exists" via JDBC Statement
Syntax error in SQL statement "DROP TABLE ORDER[*] IF EXISTS "; expected "identifier"; SQL statement:
Error executing DDL "create table order (order_id bigint not null, order_date timestamp, order_name varchar(255), primary key (order_id))" via JDBC Statement
Syntax error in SQL statement "CREATE TABLE ORDER[*] (ORDER_ID BIGINT NOT NULL, ORDER_DATE TIMESTAMP, ORDER_NAME VARCHAR(255), PRIMARY KEY (ORDER_ID)) "; expected "identifier"; SQL statement:
create table order (order_id bigint not null, order_date timestamp, order_name varchar(255), primary key (order_id)) [42001-199]
Error executing DDL "alter table order_selected_products add constraint FKrbll8c9ubhjqangdfw2sgkurw foreign key (order_entity_order_id) references order" via JDBC Statement
Syntax error in SQL statement "ALTER TABLE ORDER_SELECTED_PRODUCTS ADD CONSTRAINT FKRBLL8C9UBHJQANGDFW2SGKURW FOREIGN KEY (ORDER_ENTITY_ORDER_ID) REFERENCES ORDER[*] "; expected "identifier"; SQL statement:
alter table order_selected_products add constraint FKrbll8c9ubhjqangdfw2sgkurw foreign key (order_entity_order_id) references order [42001-199]
Error executing DDL "alter table product_orders add constraint FK9pa3r9u6x44jjxrkkhdvhu23k foreign key (orders_order_id) references order" via JDBC Statement
Syntax error in SQL statement "ALTER TABLE PRODUCT_ORDERS ADD CONSTRAINT FK9PA3R9U6X44JJXRKKHDVHU23K FOREIGN KEY (ORDERS_ORDER_ID) REFERENCES ORDER[*] "; expected "identifier"; SQL statement:
alter table product_orders add constraint FK9pa3r9u6x44jjxrkkhdvhu23k foreign key (orders_order_id) references order [42001-199]
I'm not sure why there are these syntax errors. Is this some kind of SQL dialect issue?
ORDER is a very common reserved keyword and that is the root cause of the errors you see.
Change your table name to something else, such as ORDERS, or if you really want to use that name you can try escaping it:
#Entity
#Table(name = "\"ORDERS\"")
public class OrderEntity {
....
}
List of reserved keywords for some common databases:
https://docs.oracle.com/cd/B28359_01/appdev.111/b31231/appb.htm#BABDFFBA
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql?view=sql-server-2017
https://www.postgresql.org/docs/current/sql-keywords-appendix.html
https://dev.mysql.com/doc/refman/8.0/en/keywords.html

spring.jpa.hibernate.ddl-auto=update property alters the foreign key every time

I am using spring.jpa.hibernate.ddl-auto=update property to update the schema.
As per my understanding if we do changes in the entity then table schema gets updated.
But on spring boot app startup every time alter command gets executed for the foreign key.
Following is the entity.
#Entity
#Table(name = "feedback")
#Data
public class Feedback implements Serializable {
private static final long serialVersionUID = -6420805626682233375L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "study_id")
#JsonIgnore
private Study study;
#ManyToOne(fetch= FetchType.EAGER)
#JoinColumn(name="user_id", nullable = false)
private User user;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "feedback_date", nullable = false)
private Date feedbackDate;
#Size(max = 1000)
#Column(name = "feedback", length = 1000)
private String feedback;
}
In entity you can see I have following two property for that foreign key gets created on spring boot app starts first time:
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "study_id")
#JsonIgnore
private Study study;
#ManyToOne(fetch= FetchType.EAGER)
#JoinColumn(name="user_id", nullable = false)
private User user;
So when I am restarting the app or saving the code every time foreign key constraints gets altered even if I am not changing that relationship(property).
2018-12-05 18:44:12.027 INFO 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : Starting SmartViewerApplication on LAPTOP-F95LLCU3 with PID 22736 (D:\Sagar_\SVN\SmartViewer\target\classes started by ASUS in D:\Sagar_\SVN\SmartViewer)
2018-12-05 18:44:12.027 DEBUG 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
2018-12-05 18:44:12.027 INFO 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : No active profile set, falling back to default profiles: default
2018-12-05 18:44:13.356 INFO 22736 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1329 ms
Hibernate: alter table annotation add constraint FK7hwy1g5myfk7grmm2j7faqggd foreign key (parent_id) references annotation (id)
Hibernate: alter table feedback add constraint FKfxt8nk3jikofi3x40bsjd00vt foreign key (study_id) references study (id)
Hibernate: alter table feedback add constraint FK7k33yw505d347mw3avr93akao foreign key (user_id) references user (id)
Hibernate: alter table hospital add constraint FK3922fhj7qnyc3bw5x8xl6m6xc foreign key (contact_1) references contact (id)
So what should I change to not execute alter command for the foreign key if I do not change the foreign key entity property?
Constraints are part of a database schema definition.
Constraints are the rules enforced on the data columns of a table. These are used to limit the type of data that can go into a table. This ensures the accuracy and reliability of the data in the database. Constraints could be either on a column level or a table level. The column level constraints are applied only to one column, whereas the table level constraints are applied to the whole table.
kinds of constraints are:
NOT NULL− Ensures that a column cannot have NULL value.
DEFAULT - Provides a default value for a column when none is specified.
UNIQUE - Ensures that all values in a column are different.
PRIMARY KEY - Uniquely identifies each row/record in a database table.
FOREIGN KEY - Uniquely identifies a row/record in any of the given database table.
CHECK CONSTRAINT - The CHECK constraint ensures that all the values in a column satisfies certain conditions.
INDEX - Used to create and retrieve data from the database very quickly.
Q : Is this constraint in hibernate optional or cancel to update ?
A : No. it is not optional, it is needed for relational entity.
You can also define this constraint in your DB to changes while run time if necessary but be careful not recommended.
I think this is a bug for hibernate to alter every time base on this below link (same problem):
https://discourse.hibernate.org/t/manytoone-alter-table-query-is-generating-every-time-when-inserting-a-value/1162/6

Entity primary key and sequence

i use oracle and openjpa.
i have an primary key and i want to use a sequence for its value
CREATE TABLE LOG (
ID NUMBER(10) not null,
TIMESTAMP TIMESTAMP DEFAULT (SYSDATE),
constraint PK_ID PRIMARY KEY (ID)
);
CREATE SEQUENCE ID_SEQ
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
#Entity
#Table(name="Log")
public class Log implements Serializable {
#Id
#SequenceGenerator(name="SEQ_GEN", sequenceName="ID_SEQ", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_GEN" )
#Column(name="id",nullable=false)
private long id;
#Column(name="timestamp",nullable=false)
private Timestamp timestamp;
public Log(){
}
public Log(Timestamp timestamp){
this.timestamp = timestamp;
}
..
}
#Stateless
public class LogDAO {
#PersistenceContext(unitName="logEntityPU")
private EntityManager em ;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public boolean insert(Log log){
em.persist(log);
return true;
}
...
...
}
when i check my Log object, id=0 and the timestamp is ok
but i get this error
ORA-01400: integrity constraint violation: NOT NULL check constraint.Insertion of null value not allowed
it's like jpa don't do the link with the sequence.
when i debug more, i see this error: javax.persistence.TransactionRequiredException: No active transaction for PuId=
any idea?
A trigger like this will insert the primary key if one is not provided by the app
CREATE OR REPLACE TRIGGER YOUR_SCHEMA.TRG_YOUR_TABLE
BEFORE INSERT
ON YOUR_SCHEMA.YOUR_TABLE
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
PrimaryKeyId NUMBER;
BEGIN
IF :NEW.PRIMARY_KEY_ID IS NULL THEN
SELECT your_schema.seq_your_table.nextval
INTO :NEW.PRIMARY_KEY_ID
FROM dual;
END IF;
END YOUR_SCHEMA.TRG_YOUR_TABLE;
Then do a
Select YOUR_SCHEMA.seq_your_table.currval from dual;
to get the value

Hibernate MapKeyManyToMany gives composite key where none exists

I have a Hibernate (3.3.1) mapping of a map using a three-way join table:
#Entity
public class SiteConfiguration extends ConfigurationSet {
#ManyToMany
#MapKeyManyToMany(joinColumns=#JoinColumn(name="SiteTypeInstallationId"))
#JoinTable(
name="SiteConfig_InstConfig",
joinColumns = #JoinColumn(name="SiteConfigId"),
inverseJoinColumns = #JoinColumn(name="InstallationConfigId")
)
Map<SiteTypeInstallation, InstallationConfiguration>
installationConfigurations = new HashMap<SiteTypeInstallation, InstallationConfiguration>();
...
}
The underlying table (in Oracle 11g) is:
Name Null Type
------------------------------ -------- ----------
SITECONFIGID NOT NULL NUMBER(19)
SITETYPEINSTALLATIONID NOT NULL NUMBER(19)
INSTALLATIONCONFIGID NOT NULL NUMBER(19)
The key entity used to have a three-column primary key in the database, but is now redefined as:
#Entity
public class SiteTypeInstallation implements IdResolvable {
#Id
#GeneratedValue(generator="SiteTypeInstallationSeq", strategy= GenerationType.SEQUENCE)
#SequenceGenerator(name = "SiteTypeInstallationSeq", sequenceName = "SEQ_SiteTypeInstallation", allocationSize = 1)
long id;
#ManyToOne
#JoinColumn(name="SiteTypeId")
SiteType siteType;
#ManyToOne
#JoinColumn(name="InstalationRoleId")
InstallationRole role;
#ManyToOne
#JoinColumn(name="InstallationTypeId")
InstType type;
...
}
The table for this has a primary key 'Id' and foreign key constraints+indexes for each of the other columns:
Name Null Type
------------------------------ -------- ----------
SITETYPEID NOT NULL NUMBER(19)
INSTALLATIONROLEID NOT NULL NUMBER(19)
INSTALLATIONTYPEID NOT NULL NUMBER(19)
ID NOT NULL NUMBER(19)
For some reason, Hibernate thinks the key of the map is composite, even though it isn't, and gives me this error:
org.hibernate.MappingException: Foreign key (FK1A241BE195C69C8:SiteConfig_InstConfig [SiteTypeInstallationId])) must have same number of columns as the referenced primary key (SiteTypeInstallation [SiteTypeId,InstallationRoleId])
If I remove the annotations on installationConfigurations and make it transient, the error disappears.
I am very confused why it thinks SiteTypeInstallation has a composite key at all when #Id is clearly defining a simple key, and doubly confused why it picks exactly just those two columns. Any idea why this happens? Is it possible that JBoss (5.0 EAP) + Hibernate somehow remembers a mistaken idea of the primary key across server restarts and code redeployments?
Thanks in advance,
-Lars

Resources