我创建了一些Model对象来表示一个有几个客户的公司,以及一个由公司和客户组合以及几个发票行组成的发票对象。我已经创建了以下模型对象:
@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;
}
测试:
@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());
}
当运行一个测试,创建一个有两个发票行的发票,并试图删除这个发票时,我得到了以下错误:
org.h2.jdbc.JdbcSQLException:引用完整性约束冲突:"FK3004B0A1F4110EF6:PUBLIC.INVOICELINE外键(INVOICE_ID)REFERENCES>PUBLIC.voice(ID)";SQL语句:从发票中删除〔23003-149〕
我做错了什么?
您在invoice.delete()
中尝试过吗?问题是deleteAll()
没有级联删除操作。
deleteAll()
在内部使用javax.persistence.Query
,而delete()
使用EntityManager
的remove()
方法。JPA中的级联由JPA处理,而不是由数据库处理,并且JPA不会像deleteAll()
执行的那样级联大容量删除
有关批量删除/更新的更多信息,请查看此链接。
此外:如果您已经在createInvoiceLine()
中将Invoice
设置为父级,则向Invoice
添加InvoiceLine实体是多余的。只需在执行断言之前执行invoice.refresh()
即可。
也许下面的单元测试可以解决问题。Parent1
就像你的Invoice
。而Child1
就像你的InvoiceLine
。
import java.util.*;
import javax.persistence.*;
import org.junit.*;
import play.test.*;
import models.*;
public class Parent1Test extends UnitTest {
public Parent1 p;
public Child1 c1;
public Child1 c2;
public Child1 c3;
@Before
public void setUp() {
Fixtures.deleteAllModels();
p = new Parent1();
c1 = new Child1();
c2 = new Child1();
c3 = new Child1();
}
public void byAddingParentToChilds() {
c1.parent = p;
c2.parent = p;
c3.parent = p;
c1.save();
c2.save();
c3.save();
p.refresh();
}
@Test
public void testByAddingParentToChilds() {
byAddingParentToChilds();
assertEquals(p.id, c1.parent.id);
assertEquals(3, Child1.count());
}
public void byAddingChildsToParent() {
p.childs = new ArrayList<Child1>();
p.childs.add(c1);
p.childs.add(c2);
p.childs.add(c3);
p.save();
}
@Test
public void testByAddingChildsToParent() {
// By adding childs
byAddingChildsToParent();
c1.refresh();
assertEquals(3, Child1.count());
// This will be null, because you added the childs to the
// parent while the childs are the owning side of the
// relation.
assertNull(c1.parent);
}
@Test
public void testDeletingAfterAddingParentToChilds() {
byAddingParentToChilds();
p.delete();
assertEquals(0, Parent1.count());
assertEquals(0, Child1.count());
}
@Test
public void testDeletingAfterAddingChildsToParent() {
byAddingChildsToParent();
p.delete();
assertEquals(0, Parent1.count());
assertEquals(0, Child1.count());
}
@Test(expected=PersistenceException.class)
public void testDeleteAllAfterAddingParentToChilds() {
byAddingParentToChilds();
// The cascading doesn't work for deleteAll() so this line
// will throw an exception because the child elements still
// reference the parent.
assertEquals(1, Parent1.deleteAll());
}
@Test
public void testDeleteAllAfterAddingChildsToParent() {
byAddingChildsToParent();
assertEquals(1, Parent1.deleteAll());
assertEquals(0, Parent1.count());
// Again the cascading doesn't work for deleteAll()
assertEquals(3, Child1.count());
}
}
您正在尝试删除所有发票,但仍有一些InvoiceLine链接到它。
请尝试先删除发票行,然后再删除发票。