On Delete Cascade - SQL Alchemy + Postgres - postgresql

I am trying to setup a delete cascade between a parent (Product) and a child table (ProductVariant), but it is not working. What Am I doing wrong?
from sqlalchemy.orm import relationship, backref
Base = declarative_base()
class Product(Base):
__tablename__ = 'product'
id = Column(Integer, primary_key=True)
title = Column(String)
collection_id = Column(Integer, ForeignKey('collection.id'))
class ProductVariant(Base):
__tablename__ = 'product_variant'
id = Column(Integer, primary_key=True)
title = Column(String)
product_id = Column(Integer, ForeignKey(Product.id, ondelete='CASCADE'), nullable=False)
product = relationship(Product, backref= backref("variants", cascade='delete'))

Related

FastAPI Postgres Cascade Delete

I've 2 table, "Book" and "Bookmark".
How to set a cascade on models so when they delete "Book", they will also delete "Bookmark" based on "Book".
Here's the models:
class Book(Base):
__tablename__ ="book"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
title = Column(String, nullable=False)
description = Column(String, nullable=True)
# relation
r_bookmark = relationship("BookMark", back_populates="r_book")
class BookMark(Base):
__tablename__ ="bookmark"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
title = Column(String, nullable=False)
description = Column(String, nullable=True)
book_id = Column(Integer, ForeignKey("book.id", ondelete='CASCADE'), nullable=False)
# relation
r_book = relationship("Book", back_populates="r_bookmark", cascade="all,delete")
Please help, thanks.
Thanks to MatsLindh, here's the correct answer:
class Book(Base):
__tablename__ ="book"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
title = Column(String, nullable=False)
description = Column(String, nullable=True)
# relation
r_bookmark = relationship("BookMark", back_populates="r_book", cascade="all,delete")
class BookMark(Base):
__tablename__ ="bookmark"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
title = Column(String, nullable=False)
description = Column(String, nullable=True)
book_id = Column(Integer, ForeignKey("book.id"), nullable=False)
# relation
r_book = relationship("Book", back_populates="r_bookmark")
I've add the cascade to the relation on the parent table, NOT the child table.

Spring Boot OneToOne referencedColumnName not applied

I have 2 tables:
CREATE TABLE user_profile (
id VARCHAR(36) PRIMARY KEY,
first_name VARCHAR(255) NOT NULL
);
CREATE TABLE user_phone (
id VARCHAR(36) PRIMARY KEY,
user_id VARCHAR(36),
phone_number VARCHAR(255) NOT NULL,
code VARCHAR(10) NOT NULL,
validated_at DATETIME NULL
);
ALTER TABLE user_phone ADD CONSTRAINT user_phone_FK FOREIGN KEY (user_id) REFERENCES user_profile(id) ON DELETE CASCADE;
so child has ID reference to his parent, because if I will delete parent I want this child to be deleted also.
In User class I have:
#Entity
#Table(name = "user_profile")
public class UserProfile {
...
#OneToOne
#JoinColumn(name = "id", referencedColumnName = "user_id")
private UserPhone phoneNumber;
but then when I run it I see in JPA logs:
from
user_profile userprofil0_
where
userprofil0_.id=?
why it looks there by ID ? should be by user_id field. Or I missunderstood smth there..
thanks!
One day later and finally I found the solution.
Its pretty tricky in spring and not maybe so intuitive.
So - from user_phone table Ive removed additional ID column, and now user_id is there primary key, only 1 change in sql.
Then in spring:
in UserProfile:
#OneToOne(mappedBy = "userProfile", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private UserPhone userPhone;
and in UserPhone:
#Id
#Column(name = "user_id", nullable = false)
#Type(type = "uuid-char")
private UUID id;
#OneToOne(fetch = FetchType.LAZY)
#MapsId
#JoinColumn(name = "user_id")
private UserProfile userProfile;
#PrimaryKeyJoinColumn annotation indicates that the primary key of the UserProfile is used as the foreign key value for the associated UserPhone.

JPA - WhereJoinTable to foreign key or nested select

I'm trying to add #WhereJoinTable to a property, unfortunately the field is a foreign key, and I need to look up by a property on the other table (called 'type').
I have the following tables:
business:
id
name
...
appuser:
id
email
...
role:
id
type
user_busines_role_permission:
id
appuser_id
business_id
role_id
I can do the following and it works:
#OneToMany()
#JoinTable(name = "user_business_role_permission",
joinColumns = #JoinColumn(name = "business_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "appuser_id", referencedColumnName = "id")
)
#WhereJoinTable(clause = "role_id ='3'")
private Set<AppUser> managedBy;
But I need something like:
#WhereJoinTable(clause = "role.type ='BUSINESS_MANAGER'")
or a nested select so I can select the role id and return it, is this doable?

Generated Key looks wrong when ManyToOne and OneToMany

I have two entities with a relationship, UserEntity:
#Embeddable
public class UserId extends EntityId implements Serializable {
#Column( length = CCEntity.ID_MAX_SIZE, name = ccIdCN )
private String ccId;
#Column( length = NAME_MAX_SIZE, name = userIdCN )
private String userId;
...
}
#Entity
#Table(name = TableNames.CC_Users)
public class UserEntity {
#EmbeddedId
private UserId id;
...
#OneToMany(targetEntity = ProfileEntity.class, mappedBy = "user", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE })
private List<ProfileEntity> profiles;
And the ProfileEntity:
#Embeddable
public class ProfileId extends EntityId implements Serializable {
#Column( length = CCEntity.ID_MAX_SIZE, name = ccIdCN )
private String ccId;
#Column( length = NAME_MAX_SIZE, name = profileIdCN )
private String profileId;
....
}
#Entity
#Table(name = TableNames.CC_Profile)
public class ProfileEntity {
#EmbeddedId
protected ProfileId id;
...
#ManyToOne
#JoinColumns(value = {
#JoinColumn( nullable = true, name = Columns.referenceIdCN, referencedColumnName = UserId.userIdCN ),
#JoinColumn( nullable = true, name = Columns.ccIdOfReferenceCN, referencedColumnName = UserId.ccIdCN ),
})
private UserEntity user;
When JPA creates the tables it generates the following:
Table CC_USER with primary key: cc_id, user_id. That is correct.
Table CC_PROFILE with primary key: cc_id, user_id, profile_id. Here I don't understand why JPA adds the user_id column as primary key. The table also has the columns: reference_id and cc_id_of_reference_id set as nullable.
I want property user of the ProfileEntity is optional, or nullable. If I try to add an entity with the user as null, I get :
Internal Exception: org.postgresql.util.PSQLException: ERROR: null
value in column "user_id" violates not-null constraint
thanks for any help
Finally I found the issue. I have another Entity with same TableName as ProfileEntity, but a different id. That id contains the user_id column that wasn't expected.

Play Framework [1.2.4]: unique constraints for an entity

I am using playframwork with mySQL for my web application. I have a table which requires an unique_constraint on multiple columns.
I have the entity defined as follows...
package models;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
#Entity
#Table(name = "table",
uniqueConstraints = { #UniqueConstraint(columnNames =
{ "col_1", "col_2" }) })
public class Table extends Model{
#ManyToOne
#JoinColumn(name = "col_1")
public Column1 col1;
#ManyToOne
#JoinColumn(name = "col_2")
public Column2 col2;
#ManyToOne
#JoinColumn(name = "col_3")
public Column3 col_3;
}
Column1 and Column2 are different entities with relationship with
Table entity.
When i try to insert data with duplicate "col_1 and col_2" values as
shown below i am getting no error. The data is inserted fine in the
table (MySQL).
Table table1 = new Table();
table1.col1 = new Column1("1");
table1.col2= new Column2("2);
table1.col3= new Column3("3");
table1.save();
Table table2 = new Table();
table2 .col1 = new Column1("1");
table2 .col2= new Column2("2);
table2 .col3= new Column3("3");
table2 .save();
Do i need to create unique_constraint manually on the table?
Please help me understand, if i have anything missing in the above
implementation
Thanks,
Karthik
If the table is not created by JPA, yes, you'll have to manually create the unique constraints for them to be taking affect.
If the table does not pre-exist, JPA should create the constraint for you.
JPA does not create a constraint on an already existing table.