I created some Model object to represent a company with several clients, and an invoice object that consists of a company and client combination and several invoice lines. I have created the following Model objects:
@Entity
public class Company extends Model {
@OneToMany(mappedBy="company")
public Set<Client> clients;
}
@Entity
public class Client extends Model {
@ManyToOne
public Company company;
}
@Entity
public class Invoice extends Model {
@ManyToOne
public Company company;
@ManyToOne
public Client client;
@OneToMany(mappedBy="invoice", cascade=CascadeType.ALL)
public Set<InvoiceLine> invoiceLines;
}
@Entity
public class InvoiceLine extends Model {
@ManyToOne
public Invoice invoice;
}
The test:
@Test
public void testModels() {
Client client = createClient();
Company company = createCompany();
company.clients = new HashSet<Client>();
company.clients.add(client);
company.save();
Invoice invoice = createInvoice(client, company);
InvoiceLine invoiceLine1 = createInvoiceLine(invoice);
InvoiceLine invoiceLine2 = createInvoiceLine(invoice);
Set<InvoiceLine> invoiceLines = new HashSet<InvoiceLine>();
invoiceLines.add(invoiceLine1);
invoiceLines.add(invoiceLine2);
invoice.invoiceLines = invoiceLines;
invoice.save();
Company retrievedCompany = Company.find("byName", company.name).first();
assertNotNull(retrievedCompany);
assertEquals(1, retrievedCompany.clients.size());
assertEquals(2, InvoiceLine.count());
assertEquals(1, Invoice.deleteAll());
assertNull(Invoice.all());
assertNull(InvoiceLine.all());
}
When running a test that creates an invoice with two invoice lines, and try to delete this invoice, I get the following error:
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation:
“FK3004B0A1F4110EF6: PUBLIC.INVOICELINE FOREIGN KEY(INVOICE_ID) REFERENCES >PUBLIC.INVOICE(ID)”;
SQL statement: delete from Invoice [23003-149]
What am I doing wrong?
Have you tried this with
invoice.delete()? The problem is thatdeleteAll()doesn’t cascade the delete operation.deleteAll()uses ajavax.persistence.Queryinternally, whiledelete()uses theEntityManager‘sremove()method. The cascading in JPA is handled by JPA and not by the database, and JPA does not cascade bulk deletes like the one executed bydeleteAll().Check this link for more info on bulk delete/update.
Also: adding the InvoiceLine entities to
Invoiceis redundant if you are already settingInvoiceas the parent increateInvoiceLine(). Just doinvoice.refresh()before executing the asserts.Maybe the following unit test clears things up.
The
Parent1is like yourInvoice. WhileChild1is like yourInvoiceLine.