2016-12-20 2 views
0

У меня есть объект, который содержит List<Application> applications, который сохраняется в базе данных. Я хотел бы удалить конкретный объект Application из базы данных, включая все его ссылки, т. Е. Записи в таблице сопоставления (JoinTable) с внешним ключом в Application.Hibernate не удаляет элемент из списка объектов

В то время как я могу успешно удалить базу данных строку из таблицы JoinTable отображения, я не могу получить EntityManager удалить фактическую Application строки - строку либо остается в базе данных, даже после вызова entityManager.remove(), или все таблицы в базе данных, очищается или происходит исключение.

Субъектами являются (подробности опущены для ясности):

@Entity 
@Table(name = "virtual_machine") 
public class VirtualMachine extends ExternalObject 
{ 
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinTable(name = "virtual_machine_has_applications", inverseJoinColumns = { @JoinColumn(name = "application_id", nullable = false, updatable = false) }) 
    private List<Application> applications = new ArrayList<Application>(0); 
} 

@Entity 
@Table(name = "application") 
public class Application extends Common 
{ 
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    private VirtualMachine vm; 
} 

@Entity 
@Table(name = "myapp") 
@JsonIgnoreProperties(ignoreUnknown = true) 
public class MyApp extends Application 
{ 
    @Column(name = "myapp_name") 
    private String name; 
} 

Теперь я хочу, чтобы удалить специфический MyApp из application таблицы, а также отображение строки в virtual_machine_has_applications. Это все происходит с транзакцией. Во-первых, я искать приложения для удаления:

int index = -1; 
for (int i = 0; i < virtualMachine.getApplications().size(); i++) 
{ 
    // Find Application to be deleted. virtualMachine is retrieved from within the same scope/transaction. 
    Application app = virtualMachine.getApplications().get(i);     
    if (app instanceof MyApp && someCriterion) 
    { 
     index = i; 
     break; 
    } 
} 

// Attempt to delete the application from the DB: 
virtualMachine.getApplications().remove(index); 
entityManager.merge(virtualMachine); 

Это только удаляет строку внутри virtual_machine_has_applications, но запись все еще сохраняется в application таблице. Как я могу также удалить запись из последней правильно?

Вот что я пытался, но безуспешно:

Application app = virtualMachine.getApplications().remove(index); 
entityManager.merge(virtualMachine); 
entityManager.remove(app); 

и

MyApp myApp = null; 
for (int i = 0; i < virtualMachine.getApplications().size(); i++) 
{ 
    ...   
    if (app instanceof MyApp && someCriterion) 
    { 
     index = i; 
     myApp = (MyApp) app; 
     break; 
    } 
} 

virtualMachine.getApplications().remove(index); 
entityManager.merge(virtualMachine); 
entityManager.remove(myApp); 

Оба эти попытки приводят к javax.persistence.NoResultException: No entity found for query исключения, и вся база данных протирают впоследствии.

Что я делаю неправильно?

UPDATE: Вызов только entityManager.remove(myApp); без других строк проходит без каких-либо исключений, но по какой-то причине почти каждая таблица в базе данных полностью уничтожается после этого (записи в application больше).

+0

Вы отметили оба объекта для 'CascadeType.ALL', что означает, что либо если вы собираетесь удалить' Application', он очистит 'VirtualMachine' или то же самое, если вы собираетесь очистить' VirtualMachine' it попытается очистить все относящиеся к ним приложения. Чтобы дважды проверить, откройте флаг Show_Sql – AntJavaDev

+0

Вы пытались просто em.remove (myApp); не удаляя его из коллекции? – Stan

+0

@Stan Я пробовал это - исключение не происходит, но все таблицы сущностей очищены - на самом деле, большая часть базы данных остается пустой после этого. – w128

ответ

0

Решение было:

Application app = virtualMachine.getApplications().remove(index);      
entityManager.merge(virtualMachine); 
entityManager.flush(); 
entityManager.createQuery("delete from Application where uuid=:id").setParameter("id", app.getId()).executeUpdate(); 

Я не знаю, почему использование entityManager.remove() не работает.

+0

Вы попробовали 'orphanRemoval = true'? –