Getting JPA error integrity constraint (FK_XXXXX) violated - parent key not found - spring-boot

I have two tables
CREATE TABLE stripe_product (
id NUMBER NOT NULL PRIMARY KEY,
product_id VARCHAR2(256) NOT NULL,
name VARCHAR2(256) NOT NULL,
description VARCHAR2(256),
active NUMBER(1,0),
deleted NUMBER(1,0),
created_at TIMESTAMP,
created_by NUMBER,
updated_at TIMESTAMP,
updated_by NUMBER,
deleted_at TIMESTAMP,
CONSTRAINT UC_stripe_product_id_product_id UNIQUE (id, product_id),
CONSTRAINT UC_stripe_product_product_id UNIQUE (product_id)
);
And
CREATE TABLE stripe_price (
id NUMBER NOT NULL PRIMARY KEY,
price_id VARCHAR2(256) NOT NULL,
stripe_product_product_id VARCHAR2(256) NOT NULL,
active NUMBER(1,0),
deleted NUMBER(1,0),
currency VARCHAR2(10) NOT NULL,
billing_scheme VARCHAR2(50) NOT NULL,
unit_amount NUMBER NOT NULL,
type VARCHAR2(50) NOT NULL,
recurring_aggregate_usage VARCHAR2(50),
recurring_interval VARCHAR2(50),
recurring_interval_count NUMBER,
recurring_usage_type VARCHAR2(50),
created_at TIMESTAMP,
created_by NUMBER,
updated_at TIMESTAMP,
updated_by NUMBER,
deleted_at TIMESTAMP,
CONSTRAINT UC_stripe_price_id_price_id_stripe_product_product_id UNIQUE (id, price_id, stripe_product_product_id),
CONSTRAINT UC_stripe_price_price_id UNIQUE (price_id),
CONSTRAINT FK_stripe_price_stripe_product_product_id FOREIGN KEY (stripe_product_product_id)
REFERENCES stripe_product(product_id) ON DELETE CASCADE
);
I mapped these tables using the following classes
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "stripe_product")
public class StripeProduct {
#Id
#SequenceGenerator(name = "stripe_product_seq", sequenceName = "stripe_product_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "stripe_product_seq")
private Long id;
#Column(name = "product_id", unique = true)
private String productId;
#Column(nullable = false)
private String name;
private String description;
private Boolean active;
private Boolean deleted;
#Embedded
private Audit audit = new Audit();
#Column(name = "deleted_at")
private Instant deletedAt;
public StripeProduct() {
}
public StripeProduct(Product product) {
this.productId = product.getId();
this.name = product.getName();
this.description = product.getDescription();
this.active = product.getActive();
this.deleted = product.getDeleted();
}
// getters and setter
}
Other one
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "stripe_price")
public class StripePrice {
#Id
#SequenceGenerator(name = "stripe_price_seq", sequenceName = "stripe_price_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "stripe_price_seq")
private Long id;
#Column(name = "price_id", unique = true)
private String priceId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "stripe_product_product_id")
private StripeProduct stripeProduct;
private Boolean active;
private Boolean deleted;
private String currency;
....
#Embedded
private Audit audit = new Audit();
#Column(name = "deleted_at")
private Instant deletedAt;
public StripePrice() {
}
public StripePrice(Price price, StripeProduct stripeProduct) {
Assert.notNull(price, "price cannot be null");
this.priceId = price.getId();
this.stripeProduct = stripeProduct;
this.active = price.getActive();
this.currency = price.getCurrency();
this.billingScheme = price.getBillingScheme();
this.unitAmount = price.getUnitAmount();
this.type = price.getType();
Recurring recurring = price.getRecurring();
if (recurring != null) {
this.recurringAggregateUsage = recurring.getAggregateUsage();
this.recurringInterval = recurring.getInterval();
this.recurringIntervalCount = recurring.getIntervalCount();
this.recurringUsageType = recurring.getUsageType();
}
this.deleted = price.getDeleted();
}
// getters and setters
}
In the database I have the following records
Now if I directly insert the record in the database using the following sql it works
insert into stripe_price (active, created_by, created_at, updated_by, updated_at, billing_scheme,
currency, deleted, deleted_at, price_id, recurring_aggregate_usage, recurring_interval,
recurring_interval_count, recurring_usage_type, stripe_product_product_id, type, unit_amount, id)
values (1, 0, SYSDATE, 0, SYSDATE, 'Billing scheme', 'usd', 0, null, 'adsad', 'hjgjh', 'sfsad', 1,
'asdsad', 'prod_Io2qV0NPORZhnX', 'adsad', 100, 33);
insert into stripe_price (active, created_by, created_at, updated_by, updated_at, billing_scheme,
currency, deleted, deleted_at, price_id, recurring_aggregate_usage, recurring_interval,
recurring_interval_count, recurring_usage_type, stripe_product_product_id, type, unit_amount, id)
values (1, 0, SYSDATE, 0, SYSDATE, 'Billing scheme', 'usd', 0, null, 'price_id-2', 'hjgjh', 'sfsad',
1, 'asdsadxzcxzc', 'prod_Io2qV0NPORZhnX', 'asd1234', 100, 34)
But now using JPA I am getting error
Caused by: java.sql.BatchUpdateException: ORA-02291: integrity constraint (BUILDADMIN.FK_STRIPE_PRICE_STRIPE_PRODUCT_PRODUCT_ID) violated - parent key not found
Here is my code
List<Price> prices = priceCollection.getData();
if (!CollectionUtils.isEmpty(prices)) {
prices.forEach(price -> {
String productId = price.getProduct();
StripeProduct managedStripeProduct = stripeProductRepository.findByProductId(productId).orElse(null);
if (managedStripeProduct != null) {
StripePrice newStripePrice = new StripePrice(price, managedStripeProduct);
StripePrice managedStripePrice = stripePriceRepository.save(newStripePrice);
}
});
}
In debug I found that the following SQL is making
Hibernate: select stripe_price_seq.nextval from dual
Hibernate: insert into stripe_price (active, created_by, created_at, updated_by, updated_at, billing_scheme, currency, deleted, deleted_at, price_id, recurring_aggregate_usage, recurring_interval, recurring_interval_count, recurring_usage_type, stripe_product_product_id, type, unit_amount, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
binding parameter [1] as [BIT] - [true]
binding parameter [2] as [BIGINT] - [0]
binding parameter [3] as [TIMESTAMP] - [2021-01-25T23:18:11.104Z]
binding parameter [4] as [BIGINT] - [0]
binding parameter [5] as [TIMESTAMP] - [2021-01-25T23:18:11.104Z]
binding parameter [6] as [VARCHAR] - [per_unit]
binding parameter [7] as [VARCHAR] - [usd]
binding parameter [8] as [BIT] - [null]
binding parameter [9] as [TIMESTAMP] - [null]
binding parameter [10] as [VARCHAR] - [price_1ICQl8JOji9YLkEKmju4jUmu]
binding parameter [11] as [VARCHAR] - [null]
binding parameter [12] as [VARCHAR] - [month]
binding parameter [13] as [BIGINT] - [1]
binding parameter [14] as [VARCHAR] - [licensed]
binding parameter [15] as [BIGINT] - [30]
binding parameter [16] as [VARCHAR] - [recurring]
binding parameter [17] as [BIGINT] - [100000]
binding parameter [18] as [BIGINT] - [80]
As you can notice that there is no stripe_product_product_id when hibernate is making SQL. I think that's why it is generating error.
Although I am setting it on StripePrice but unable to find why I am betting error. Can anyone please explain what I am doing wrong ? And how I can I resolve this issue?
Thanks

I have solved the problem. Actually the problem was I have different name for column. In stripe_product table column name is product_id. While in stripe_price table column name is stripe_product_product_id. So I have to use the following in my mapping
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "stripe_product_product_id", referencedColumnName = "product_id", nullable = false)
private StripeProduct stripeProduct;
So basically referencedColumnName = "product_id" was missing that's why JPA unable to find the product_id value from stripe_product table. Hopefully it will be useful for others too.

Related

Hibernate Composite key problem with partial joining with other entity

Hibernate Composite key problem with partial joining with other entity.
Below code was working for javax.persistence_1.0.0.0_2.0 (Toplink), however same is not working for under Spring Boot (Spring Boot JPA starter - jakarta.persistence-api-2.2.3)
#Table(name = "EMPLOYEE")
#IdClass(EmployeePK.class)
public class Employee implements Serializable {
#Id
#Column(name = "EMP_NUMBER", nullable = false, length = 4000, insertable = false, updatable = false)
private String empNo;
#Id
#Column(name = "RGSN_ID", nullable = false, insertable = false, updatable = false)
private Long registId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns( { #JoinColumn(name = "PRJ_ID", referencedColumnName = "PRJ_ID"),
#JoinColumn(name = "EMP_NUMBER",
referencedColumnName = "EMP_NUMBER") })
private Projects projects;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "RGSN_ID")
private Organization organization;
//other fields
//created_by, creation_date, last_update_date, last_updated_by, status
}
Composite Key of Employee Table
public class EmployeePK
implements Serializable {
private String empNo;
private Long registId;
// getter setter equals hashcode
}
Project Table
#Table(name = "PROJECTS")
#IdClass(ProjectsPK.class)
public class Projects implements Serializable {
#Id
#Column(name = "PRJ_ID", nullable = false, insertable = false, updatable = false)
private Long prjId;
#Id
#Column(name = "EMP_NUMBER", nullable = false, length = 4000)
private String empNo;
#OneToMany(mappedBy = "projects")
private List<Employee> empList;
//other fields
//created_by, creation_date, last_update_date, last_updated_by, status
}
Composite keys for Project table
public class ProjectsPK
implements Serializable {
private Long prjId;
private String empNo;
// getter setter equals hashcode
}
Console Exception:
insert
into
EMPLOYEE
(created_by, creation_date, last_update_date, last_updated_by, status, prj_id, emp_number, rgsn_id)
values
(?, ?, ?, ?, ?, ?, ?, ?)
o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [abc#c.com]
o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [TIMESTAMP] - [2022-03-16 18:52:37.587915]
o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [TIMESTAMP] - [2022-03-16 18:52:37.587915]
o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [abc#c.com]
o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [VARCHAR] - [A]
o.h.type.descriptor.sql.BasicBinder : binding parameter [6] as [BIGINT] - [435]
o.h.type.descriptor.sql.BasicBinder : binding parameter [7] as [VARCHAR] - [123]
o.h.type.descriptor.sql.BasicBinder : binding parameter [8] as [VARCHAR] - [123]
o.h.type.descriptor.sql.BasicBinder : binding parameter [9] as [BIGINT] - [null]
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: S1093
o.h.engine.jdbc.spi.SqlExceptionHelper : The index 9 is out of range.
com.microsoft.sqlserver.jdbc.SQLServerException: The index 9 is out of range.
In above exception it shows two entries for emp_number 123 and because of that index is coming 9.
Not getting what could be the problem also added insertable = false, updatable = false at those entries.

Spring Data JPA + Postgres - Unable to insert data with One to One mapping

I have a UserInfo and AddressInfo entity classes and they have one to one association. UserInfo uses sequence to add primary key but I am getting below error;
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
UserInfo Entity
#Entity
#Table(name = "userinfo")
public class UserInfo {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userid_seq")
#SequenceGenerator(name="userid_seq", allocationSize=1)
private Long userId;
private String firstName;
private String lastName;
private String email;
private String username;
private String password;
#OneToOne(mappedBy = "userInfo", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private AddressInfo addressInfo;
//Getters - Setters
}
AddressInfo Entity
#Entity
#Table(name = "addressinfo")
public class AddressInfo {
#Id
private Long addressId;
private String homeAddress;
private String homeCity;
private String homeState;
private String homeZip;
#OneToOne
#MapsId
#JoinColumn(name = "address_id")
private UserInfo userInfo;
//Getters - Setters
}
UserInfo Table
CREATE TABLE userinfo (
user_id INTEGER NOT NULL DEFAULT nextval('userid_seq') PRIMARY KEY ,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
username VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL
);
AddressInfo Table
CREATE TABLE addressinfo (
address_id INTEGER NOT NULL PRIMARY KEY,
home_address VARCHAR(100) NULL,
home_city VARCHAR(100) NULL,
home_state VARCHAR(100) NULL,
home_zip VARCHAR(100) NULL,
CONSTRAINT fk_addinfo
FOREIGN KEY(address_id)
REFERENCES userinfo(user_id)
);
I thought my sequence had some issues but I could see that if I remove the child entity then its is inserting into the UserInfo table successfully but getting above error when I add OneToOne mapping. Seems like I have issues with my Primary key. I see similar questions but I could not find what is going on here. A help would be really appreciated.
Two solutions come to mind:
A single transaction that inserts both Userinfo and Addressinfo. With the second insert using the sequence currval to define the id.
create table addressinfo (
address_id integer default currval('userid_seq') primary key,
home_address varchar(100) null,
home_city varchar(100) null,
home_state varchar(100) null,
home_zip varchar(100) null,
constraint fk_addinfo
foreign key(address_id)
references userinfo(user_id)
);
do $$
begin
insert into userinfo (first_name, last_name, email, username, password)
values ('Jane','Smith','j.smith#thisplace.org','js','psojHvIEJNB');
insert into addressinfo( home_address, home_city, home_state,home_zip)
values ('1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh');
end;
$$;
A single statement handling the insert for both tables:
with newuser (user_id) as
(insert into userinfo (first_name, last_name, email, username, password)
values ('Joe','Smith','j.s.smith#thisplace.org','js2','+949+fsrgwDGKJS58')
returning user_id
) --select id from newuser;
insert into addressinfo(address_id, home_address, home_city, home_state,home_zip)
select user_id,'1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh'
from newuser;
However neither is a good plan. A 1:1 relationships are always questionable. In this case they are not. What happens when user Jane Smith stores her address, then insists that her husband, Joe, have the same address. You wind up with DUPLICATE addresses. See example here. You might be better off giving addressinfo its own PK sequence and putting address_id as a column and FK into userinfo

how to fix incompatible foreign key constraints spring boot

I have a spring boot application where I have two entities in a relationship. MeetingsSetting and meetingTime. One MeetingSetting can have multiple meetingTimes and one meetingtime belongs to one Meetingsetting.
I generate the databases through sql script and reference the foreing key their for the meetingTime entity. But I am getting the following error:
Caused by: java.sql.SQLException: Referencing column 'meeting_name' and referenced column 'id' in foreign key constraint 'FK1omm6fk51xdsd0kysqbmleweg' are incompatible.
THe funny thing is I am not referencing the id anywhere not in my entity nor in my script. This is how my entity and script looks like:
meetingSetting:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name")
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meeting_Name", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingTime:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#Column(name = "meeting_name",insertable = false, updatable = false )
private String meetingName;
#ManyToOne
#JoinColumn(name = "meeting_name", nullable = false)
private MeetingsSetting meeting_Name;
}
and this is my script where I generate my tables:
-- auto-generated definition
create table meeting_settings
(
id bigint auto_increment
primary key,
meeting_name varchar(255) null,
meeting_pw varchar(255) null,
meeting_url varchar(255) null
);
create table meeting_times
(
id bigint auto_increment
primary key,
meeting_date varchar(255) null,
start_time varchar(255) null,
end_time varchar(255) null,
meeting_name varchar(255) null,
constraint fk_meeting_times_meeting_name
foreign key (meeting_name) references meeting_settings (meeting_name)
);
What could cause such an error? because I am not referencing anywhere the id.
UPDATE:
spring.datasource.url=jdbc:mysql://localhost:3306/coorporate_blinddate?createDatabaseIfNotExist=true&useSSL=true&serverTimezone=UTC
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=../generate.sql
spring.jpa.show-sql= true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto = update
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=Test1234##1&
server.port=8081
Hibernate Sequence:
Hibernate: create table meeting_settings (id bigint not null auto_increment, meeting_name varchar(255), meeting_pw varchar(255), meeting_url varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table meeting_settings_meeting_time (meetings_setting_id bigint not null, meeting_name bigint not null, primary key (meetings_setting_id, meeting_name)) engine=InnoDB
Hibernate: create table meeting_times (id bigint not null auto_increment, meeting_date varchar(255), end_time varchar(255), meeting_name varchar(255), start_time varchar(255), primary key (id)) engine=InnoDB
Hibernate: alter table meeting_settings drop index UK_klg4vqmhi7o9qff83ymly598o
Hibernate: alter table meeting_settings add constraint UK_klg4vqmhi7o9qff83ymly598o unique (meeting_name)
Hibernate: alter table meeting_settings_meeting_time drop index UK_jsn83wsxfkpm1xfencvsdkqj1
Hibernate: alter table meeting_settings_meeting_time add constraint UK_jsn83wsxfkpm1xfencvsdkqj1 unique (meeting_name)
Hibernate: alter table meeting_settings_meeting_time add constraint FK9lq62drkkslq6x381b3lieruu foreign key (meeting_name) references meeting_times (id)
Hibernate: alter table meeting_settings_meeting_time add constraint FKglhgb5vgsviqm7t6vtmdx5e7t foreign key (meetings_setting_id) references meeting_settings (id)
Hibernate: alter table meeting_times add constraint FK1omm6fk51xdsd0kysqbmleweg foreign key (meeting_name) references meeting_settings (id)
A table which is generated
meeting_settings_meeting_time
meetings_setting_id
meeting_name
PRIMARY
UK_jsn83wsxfkpm1xfencvsdkqj1
FK9lq62drkkslq6x381b3lieruu
FKglhgb5vgsviqm7t6vtmdx5e7t
UK_jsn83wsxfkpm1xfencvsdkqj1
Looks like your meeting_name column is not unique in order to do the relationship you have done. Add unique = true
#Column(name = "meeting_name", unique = true)
private String meetingName;
And
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(inverseJoinColumns=#JoinColumn(name="meeting_name"))
private Set<MeetingTime> meetingTime = new HashSet<>();

spring sql Invalid column name

getting
com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name
'partnerIdPartner'.
application.properties:
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Table creation:
CREATE TABLE [partnersystem] (
[idPartnerSystem] INT IDENTITY(1,1) ,
[partner_idPartner] INT NOT NULL DEFAULT NULL ,
[Name] NVARCHAR(45) NULL DEFAULT NULL ,
[Domain] NVARCHAR(45) NULL DEFAULT NULL ,
[Code] NVARCHAR(45) NULL DEFAULT NULL ,
[PartnerSystem_idSystem] INT NOT NULL DEFAULT NULL ,
[UpdateUser] NVARCHAR(45) NULL DEFAULT NULL ,
[UpdateDT] DATETIME NULL DEFAULT NULL ,
CONSTRAINT [partnersystem_PRIMARY] PRIMARY KEY CLUSTERED ([idPartnerSystem]), CONSTRAINT [partnersystem_fk_PartnerSystem_partner] FOREIGN KEY ("partner_idPartner") REFERENCES "partner" ( "idPartner" ) ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT [partnersystem_fk_PartnerSystem_System] FOREIGN KEY ("PartnerSystem_idSystem") REFERENCES "system" ( "idSystem" ) ON UPDATE NO ACTION ON DELETE NO ACTION);
CREATE INDEX [partnersystem_fk_PartnerSystem_partner] ON [partnersystem] ([partner_idPartner]);
CREATE INDEX [partnersystem_fk_PartnerSystem_System] ON [partnersystem] ([PartnerSystem_idSystem]);
JPA Entity:
#Entity
#Table(name = "partnersystem")
public class PartnerSystem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idPartnerSystem")
private int idPartnerSystem;
#Column(name = "partner_idPartner" )
private int partnerIdPartner;
#Column(name = "Name")
private String name;
#Column(name = "Domain" )
private String domain;
#Column(name = "Code" )
private String code;
#Column(name = "PartnerSystem_idSystem" )
private int partnerSystemIdSystem;
#Column(name = "UpdateUser" )
private String updateUser;
my repository:
#Repository
public interface PartnerSystemRepository extends JpaRepository<PartnerSystem,
Integer>{
public PartnerSystem findByPartnerIdPartner(int partnerIdPartner);
}
executing simple query throws an error.
public List<Object[]> findAllPartnerSystem(int id) {
String test =
"SELECT idPartnerSystem, partnerIdPartner, name, domain, code, partnerSystemId" +
" FROM PartnerSystem " +
"WHERE partnerIdPartner = ?"
;
Query query = em.createNativeQuery(test);
query.setParameter(1, id);
List<Object[]> results = query.getResultList();
for (Object[] row : results) {
}
return results;
}
In native queries you have to use the column name not the property name:
"SELECT idPartnerSystem, partner_idPartner, name, domain, code, PartnerSystem_idSystem" +
" FROM partnersystem " +
"WHERE partner_idPartner=
But I suggest using JPQL queries and not native queries.

how to use bidirectional many to many mapping following error is thrown Cannot add or update a child row: a foreign key constraint fails

I am trying to implement the birectional many to many mapping (question,tags,question_tag) by using the following tables using Spring & Hibernate
TABLE user:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NOT NULL,
`password` varchar(255) DEFAULT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE question:
CREATE TABLE `question` (
`qid` int(11) NOT NULL AUTO_INCREMENT,
`questiontitle` varchar(255) DEFAULT NULL,
`questionbody` varchar(3000) DEFAULT NULL,
`uid` int(11) NOT NULL,
`votes` int(11) NOT NULL,
`created_on` DATETIME NOT NULL DEFAULT NOW(), -- or CURRENT_TIMESTAMP
PRIMARY KEY (`qid`),
CONSTRAINT `fk_user_id` FOREIGN KEY (`uid`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE tags:
CREATE TABLE `tags` (
`tagid` int(11) NOT NULL AUTO_INCREMENT,
`tag` varchar(255) DEFAULT NULL,
PRIMARY KEY (`tagid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE question_tag:
CREATE TABLE `question_tag` (
`qid` int(11) NOT NULL,
`tagid` int(11) NOT NULL,
PRIMARY KEY (`qid`,`tagid`),
CONSTRAINT `fk_qt_qid` FOREIGN KEY (`qid`) REFERENCES `question` (`qid`),
CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Model used are
Question.Java
#Entity
#Table(name="question")
#NamedQuery(name="Question.findAll", query="SELECT q FROM Question q")
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int qid;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="created_on")
private Date createdOn;
private String questionbody;
private String questiontitle;
private int uid;
private int votes;
//bi-directional many-to-one association to Answer
#OneToMany(mappedBy="question")
private Set<Answer> answers = new HashSet<>();
//bi-directional many-to-one association to QuestionComment
#OneToMany(mappedBy="question")
private Set<QuestionComment> questionComments = new HashSet<>();
//bi-directional many-to-many association to Tag
#ManyToMany(targetEntity = Tag.class,cascade = { CascadeType.ALL })
#JoinTable(name = "question_tag",
joinColumns = { #JoinColumn(name = "qid") },
inverseJoinColumns = { #JoinColumn(name = "tagid") })
private Set<Tag> tags;
//bi-directional many-to-one association to UserQuestionUpvote
#OneToMany(mappedBy="question")
private Set<UserQuestionUpvote> userQuestionUpvotes = new HashSet<>();
public Question() {
}
}
Tag.Java
#Entity
#Table(name="tags")
#NamedQuery(name="Tag.findAll", query="SELECT t FROM Tag t")
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int tagid;
private String tag;
//bi-directional many-to-many association to Question
#ManyToMany(mappedBy = "tags")
private Set<Question> questions ;
public Tag() {
}
}
There is a questionServiceImpl class which call the questionRepository.save method.
#Service
public class QuestionServiceImpl implements QuestionService {
#Autowired
private QuestionRepository questionRepository;
#Override
public void save(Question question) {
// TODO Auto-generated method stub
questionRepository.save(question);
}
}
Now in the controller when the call to QuestionServiceImpl.save is made insert call to the tables question, tags & question_tag is made but Cannot add or update a child row error is thrown
Hibernate: insert into question (created_on, questionbody, questiontitle, uid, votes) values (?, ?, ?, ?, ?)
Hibernate: insert into tags (tag, tagid) values (?, ?)
Hibernate: insert into question_tag (qid, tagid) values (?, ?)
17:43:36.692 [http-bio-9191-exec-5] ERROR o.h.e.j.s.SqlExceptionHelper#129 Cannot add or update a child row: a foreign key constraint fails (`Forum`.`question_tag`, CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`))
Jul 10, 2018 5:43:36 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`Forum`.`question_tag`, CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`))
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:400)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2447)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1901)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2113)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2049)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2034)

Resources