How to delete on cascade?
See original GitHub issueIssue type:
[ ] question [x] bug report [ ] feature request [ ] documentation issue
Database system/driver:
[ ] cordova
[ ] mongodb
[ ] mssql
[ x] mysql
/ mariadb
[ ] oracle
[ ] postgres
[ ] sqlite
[ ] sqljs
[ ] react-native
TypeORM version:
[ x] latest
[ ] @next
[ ] 0.x.x
(or put your version here)
Steps to reproduce or a small repository showing the problem:
I have a Fulfillment
entity that has a @OneToOne
Address
relation. When I create a Fulfillment
, I only need to save once because the Address
is created on cascade. When I delete the Fulfillment
, I must delete Fulfillment
and Address
in two separate removes, because it is not deleted when Fulfillment
is deleted alone. Why is this?
import Fulfillment from "../src/entity/Fulfillment";
import { createConnection, Connection } from "typeorm";
import Branch from "../src/entity/Branch";
import Address from "../src/entity/Address";
// Use for reference on writing good tests: https://github.com/typeorm/typeorm/blob/master/test/functional/repository/clear/repository-clear.ts
// https://github.com/typeorm/typeorm/blob/master/test/github-issues/70/issue-70.ts
describe("Fulfillment", () => {
let connection: Connection;
beforeAll(async () => {
connection = await createConnection();
});
beforeEach(async () => {
await connection.synchronize(true);
});
afterAll(async () => {
await connection.close();
});
it("should create an Address", async () => {
const address = new Address();
address.addressLine1 = "114 5th Ave";
address.city = "New York";
address.stateCode = "NY";
address.postalCode = "10011";
const fulfillment = new Fulfillment();
fulfillment.branchDid = "41970";
fulfillment.deliveryInstructions = "test";
fulfillment.address = address;
await connection.manager.save(fulfillment);
expect(fulfillment.fulfillmentId).toBe(1);
expect(fulfillment.address.addressId).toBe(1);
});
it("should delete Address on Cascade" , async () => {
const address = new Address();
address.addressLine1 = "114 5th Ave";
address.city = "New York";
address.stateCode = "NY";
address.postalCode = "10011";
const fulfillment = new Fulfillment();
fulfillment.branchDid = "41970";
fulfillment.deliveryInstructions = "test";
fulfillment.address = address;
await connection.manager.save(fulfillment);
// check if fulfillment has been saved
const loadedFullfillments = await connection.manager.find(Fulfillment);
expect(loadedFullfillments.length).toBe(1);
await connection.manager.remove(fulfillment);
// TODO: This shouldn't be necessary but it's fine for now.
await connection.manager.remove(fulfillment.address);
const loadedFulfillmentsAfterDelete = await connection.manager.find(Fulfillment);
expect(loadedFulfillmentsAfterDelete.length).toBe(0);
const loadedAddressesAfterDelete = await connection.manager.find(Address);
expect(loadedAddressesAfterDelete.length).toBe(0);
});
});
import Address from "./Address";
import { Timestamp, Column, OneToOne, PrimaryGeneratedColumn, Entity, JoinColumn } from "typeorm";
import Order from "./Order";
// KLT: TODO
// Need this to transform string to date from json.
// Example: https://github.com/typeorm/typeorm/blob/master/test/functional/columns/value-transformer/value-transformer.ts
// Example: https://github.com/typeorm/typeorm/blob/master/test/github-issues/1140/entity/Post.ts
// const transformer = {
// from(value: string): Date {
// return new Date();
// },
// to(value: number): Date {
// return new Date(value);
// }
// };
@Entity()
class Fulfillment {
@PrimaryGeneratedColumn()
fulfillmentId: number;
@Column("varchar", { default: null })
branchDid: string;
@Column("timestamp", { default: () => "CURRENT_TIMESTAMP" })
deliveryBeginTime: Timestamp;
@Column("timestamp", { default: () => "CURRENT_TIMESTAMP" })
deliveryEndTime: Timestamp;
@OneToOne(type => Address, { cascade: true, onDelete: "CASCADE", primary: true})
address: Address;
@Column("varchar", { length: 2083, default: null })
trackingLink: string;
@Column("varchar", { default: null })
deliveryInstructions: string;
@Column("varchar", { length: 50, default: "Postmates" })
deliveryMethod: string;
}
export default Fulfillment;
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
class Address {
@PrimaryGeneratedColumn()
addressId: number;
@Column()
addressLine1: string;
@Column({default: null})
addressLine2: string;
@Column()
city: string;
@Column()
stateCode: string;
@Column()
postalCode: string;
}
export default Address;
Issue Analytics
- State:
- Created 5 years ago
- Comments:9
Top Results From Across the Web
Using the ON DELETE CASCADE Option - IBM
Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in...
Read more >MySQL - ON DELETE CASCADE Constraint - GeeksforGeeks
ON DELETE CASCADE constraint is used in MySQL to delete the rows from the child table automatically, when the rows from the parent...
Read more >How to add 'ON DELETE CASCADE' in ALTER TABLE ...
Choose your constraint on the left side (if there are more than one). Then on the right side, collapse "INSERT And UPDATE Specification"...
Read more >SQL Server: Foreign Keys with cascade delete - TechOnTheNet
A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the...
Read more >Good explanation of cascade (ON DELETE/UPDATE) behavior
SQL:2011 Spec · ON DELETE CASCADE : if a row of the referenced table is deleted, then all matching rows in the referencing...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Have you tried adding the decorator
@JoinColumn()
below@OneToOne
? This will add the columnaddressId
on theFulfillment
table, which I think is a prerequisite for cascade delete to work.@JoinColumn()
can be used on either side of the relation, depending in which table you want to store the anchor id. Important: it must be set only on one side of the relation, see the docs.@filipjnc I think I figured it out. Does this intuitively make sense?