Играть! рамки ссылочной целостности при удалении - PullRequest
2 голосов
/ 06 марта 2012

Я создал некоторый объект 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 FOREIGN KEY (INVOICE_ID) REFEREN(Я БЫ)";Оператор SQL: удалить из счета-фактуры [23003-149]

Что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 07 марта 2012

Вы пробовали это с invoice.delete()? Проблема в том, что deleteAll() не каскадирует операцию удаления.

deleteAll() использует javax.persistence.Query внутри, в то время как delete() использует EntityManager метод remove(). Каскадирование в JPA обрабатывается JPA, а не базой данных, и JPA не выполняет каскадное массовое удаление, как то, которое выполняется deleteAll().
Проверьте эту ссылку для получения дополнительной информации о массовом удалении / обновлении .

Также: добавление сущностей InvoiceLine к Invoice является излишним, если вы уже устанавливаете Invoice в качестве родителя в createInvoiceLine(). Просто выполните 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());
    }

}
0 голосов
/ 07 марта 2012

Вы пытаетесь удалить все счета-фактуры, но с ними все еще связаны некоторые строки счетов-фактур.

Попробуйте сначала удалить строки счета-фактуры, а затем - счета-фактуры.

...