How to delete entity related to another entity - spring

I have this entities:
Batch, Malt, Country - batch contains malts (#ManyToMany), malt came from some country (#ManyToOne).
Relations are as following:
Batch:
#JoinTable(name="batch_malt",
joinColumns = #JoinColumn(name="batch_id"),
inverseJoinColumns = #JoinColumn(name="malt_id"))
private Set<Malt> malts = new HashSet<>();
Malt:
#NotNull
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="country_id")
private Country country;
#ManyToMany(mappedBy="malts")
private Set<Batch> batches;
Country:
No mappinge since it is #ManyToOne from Malt.
Country Service:
#Override
public void deleteById(Long countryIdToDelete) {
Set<Malt> malts = maltRepository.findByCountry_id(countryIdToDelete);
if (malts != null) {
for (Malt tempMalt : malts) {
log.debug("Deleting country from malt number: " + tempMalt.getMaltName());
tempMalt.setCountry(null);
}
maltRepository.deleteById(countryIdToDelete);
}
}
I want to delete Country (I don't want to delete Malt - null shoul be instead)
When I'm trying do delete Country I get:
There was an unexpected error (type=Internal Server Error, status=500).
could not execute statement; SQL [n/a]; constraint ["FKM636T1NDS3GNKJC6WG8MCG21L: PUBLIC.BATCH_MALT FOREIGN KEY(MALT_ID) REFERENCES PUBLIC.MALT(ID) (2)"; SQL statement: delete from malt where id=? [23503-197]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FKM636T1NDS3GNKJC6WG8MCG21L: PUBLIC.BATCH_MALT FOREIGN KEY(MALT_ID) REFERENCES PUBLIC.MALT(ID) (2)"; SQL statement:
delete from malt where id=? [23503-197]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.h2.jdbc.JdbcSQLException: Naruszenie więzów integralności: "FKM636T1NDS3GNKJC6WG8MCG21L: PUBLIC.BATCH_MALT FOREIGN KEY(MALT_ID) REFERENCES PUBLIC.MALT(ID) (2)"
Referential integrity constraint violation: "FKM636T1NDS3GNKJC6WG8MCG21L: PUBLIC.BATCH_MALT FOREIGN KEY(MALT_ID) REFERENCES PUBLIC.MALT(ID) (2)"; SQL statement:
delete from malt where id=? [23503-197]
What should I change to be able to delete Country?
Link to whole repo: https://github.com/fangirsan/maruszka-new

Related

org.hibernate.exception.ConstraintViolationException only during unit test, Cascade Delete not working

I have a Spring Kotlin project where I use JPA (Hibernate?) entities to map my database tables.
A Project is linked to multiple ProjectMaps. When a Project is deleted, I want all the ProjectMaps to be deleted also.
The DDL for my local H2 db is as follows.
CREATE TABLE IF NOT EXISTS "project" (
id INT AUTO_INCREMENT PRIMARY KEY,
other fields...
);
CREATE TABLE IF NOT EXISTS "project_map" (
project_id INT NOT NULL,
tag_id INT NOT NULL,
CONSTRAINT pk_project_id_tag_id PRIMARY KEY (project_id, tag_id),
CONSTRAINT fk_project_map_project_id
FOREIGN KEY (project_id) REFERENCES "project" (id)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT fk_project_map_tag_id
FOREIGN KEY (tag_id) REFERENCES "tag" (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
The entities are as follows.
Project
#Entity
#Table(name = "project")
class Project(
other fields...,
#JsonIgnore
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
) {
#JsonIgnore
#OneToMany(mappedBy = "projectMapId.project", cascade = [CascadeType.ALL], orphanRemoval = true)
val projectMaps = mutableSetOf<ProjectMap>()
}
ProjectMap
#Entity
#Table(name = "project_map")
class ProjectMap(
#EmbeddedId
var projectMapId: ProjectMapId,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ProjectMap) return false
if (projectMapId != other.projectMapId) return false
return true
}
override fun hashCode(): Int {
return projectMapId.hashCode()
}
}
#Embeddable
class ProjectMapId(
#ManyToOne
#JoinColumn(name = "project_id", nullable = false, referencedColumnName = "id")
var project: Project,
#ManyToOne
#JoinColumn(name = "tag_id", nullable = false, referencedColumnName = "id")
var tag: Tag,
) : Serializable {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ProjectMapId) return false
if (project != other.project) return false
if (tag != other.tag) return false
return true
}
override fun hashCode(): Int {
var result = project.hashCode()
result = 31 * result + tag.hashCode()
return result
}
}
I have a ProjectRepository interface that extends JpaRepository. In my code somewhere I call projectRepo.deleteAllInBatch(projectsToBeDeleted), and when I run it I see that the ProjectMaps are indeed deleted together with the Projects. But when I write a unit test for that method, I get this error.
[main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions - Referential integrity constraint violation: "FKM2O7A1Y4HFNXYHQEYBQI9AABY: PUBLIC.PROJECT_MAP FOREIGN KEY(PROJECT_ID) REFERENCES PUBLIC.PROJECT(ID) (CAST(1 AS BIGINT))"; SQL statement:
delete from project where id=? [23503-210]
[main] ERROR com.dbs.localisemanagement.exception.RestExceptionHandler.handleAllUncaughtException - [L9y5j][500][1-Unknown] could not execute statement; SQL [n/a]; constraint ["FKM2O7A1Y4HFNXYHQEYBQI9AABY: PUBLIC.PROJECT_MAP FOREIGN KEY(PROJECT_ID) REFERENCES PUBLIC.PROJECT(ID) (CAST(1 AS BIGINT))"; SQL statement:
delete from project where id=? [23503-210]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FKM2O7A1Y4HFNXYHQEYBQI9AABY: PUBLIC.PROJECT_MAP FOREIGN KEY(PROJECT_ID) REFERENCES PUBLIC.PROJECT(ID) (CAST(1 AS BIGINT))"; SQL statement:
delete from project where id=? [23503-210]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
The error is at this line projectRepo.deleteAllInBatch(projectsToBeDeleted), so I see that it is because there are still existing ProjectMaps that's why the Projects cannot be deleted.
I reckon it is because the Cascade Delete is not working during unit test, but I don't know why. Anyone has any idea on this?

Spring JPA #ManyToOne and #OneToMany delete

I use Spring Boot backend for my application. I have 2 entities, Post and Comment. There are multiply comments for my posts. What I want:
If I delete my post, I want to delete my comments as well.
If I delete a comment, I want to delete only that one comment.
Here is my Post entity:
#Entity
public class Post{
...
#OneToMany(cascade = CascadeType.ALL, mappedBy = "post")
private Set<Comment> comments;
...
}
Here is my Comment entity:
#Entity
public class Comment{
...
#ManyToOne
#JoinColumn(name = "post_id", nullable = false)
private Post post;
...
}
This is how I tried to delete my comment:
#DeleteMapping("/{commentId}")
#RoleSecured({})
public ResponseEntity<Object> delete(#PathVariable Long commentId) {
commentRepository.deleteById(commentId);
return ResponseEntity.ok().build();
}
And this is how I tried to delete my post:
#DeleteMapping("/{postId}")
#RoleSecured({})
public ResponseEntity<Object> delete(#PathVariable Long postId) {
Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not present in database"));
postRepository.delete(post);
}
This is my last try but I tried a lot of things, can you help me please how can I implement both deletes.
Delete of the post exception:
021-11-24 15:05:48.479 ERROR 23332 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot delete or update a parent row: a foreign key constraint fails (`buildtogether`.`comment`, CONSTRAINT `fk_comment_post_id` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`))
2021-11-24 15:05:48.480 INFO 23332 --- [nio-8080-exec-1] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2021-11-24 15:05:48.588 ERROR 23332 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] 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
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`buildtogether`.`comment`, CONSTRAINT `fk_comment_post_id` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.27.jar:8.0.27]
Delete of the comment exception: no exception, but not delete the comment.

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

sequence does not exist, hibernate and JPA 2.1

I am getting an error saying
`Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist`
This error happens when I try to create a user.
#RequestMapping(method = POST)
public UserDto createUser(#RequestBody userDto user) {
Preconditions.checkNotNull(user);
return Preconditions.checkNotNull(service.create(user));
}
I am however able to delete and get just not create nor update. What is also frustrating is I get no error when trying to update, it just doesn't so it.
I am not getting any real lead on where to look. I have tried many different methods to resolve this with no avail.
I found a post that had this:
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQUENCE1")
#SequenceGenerator(name="SEQUENCE1", sequenceName="SEQUENCE1", allocationSize=1)
private int user_id;
At this link: SOF link
It is complaining about this entity which I generated with netbeans and I am currently using Intellij. Any advice would be appreciated.
The code that creates new Campaign entity seems to be incorrect.
public CampaignDto create(CampaignDto campaignDto) {
Campaign campaign = mapper.mapReverse(campaignDto);
System.out.println(campaign.toString());
// Following 2 lines must be added to obtain and use managed Shop entity
Shop existingShop = shopRepository.findOne(campaignDto.getShopId());
campaign.setShop(existingShop);
campaign = campaignRepository.save(campaign);
CampaignDto createdCampaign = mapper.map(campaign);
return createdCampaign;
}
It looks like you might not be setting Campaign.shopId field when creating new Campaign.
#JoinColumn(name = "SHOP_ID", referencedColumnName = "SHOP_ID")
#ManyToOne(optional = false)
private Shop shopId;
You might want to rename this field to just shop to make it clear what it holds as it's not just an identifier.
Depending on how you are persisting new objects you might need to add CascadeType.ALL on #ManyToOne to ensure that a new Shop is persisted together with a new Campaign.
#ManyToOne(optional = false, cascade = CascadeType.ALL)
Go to your application property file and put
hibernate.hbm2ddl.auto=true; It might be helpful Hibernate created this sequence and added a new row

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

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!

Resources