Как обновить список после удаления элемента этого списка - PullRequest
1 голос
/ 31 декабря 2010

Мне потребуется время, чтобы объяснить это, поэтому, пожалуйста, оставайтесь со мной. У меня есть таблица NewsFeed, которая имеет отношение OneToMany к себе.

@Entity
public class NewsFeed(){
    ...
    @ManyToOne(optional=true, fetch=FetchType.LAZY)
    @JoinColumn(name="REPLYTO_ID")
    private NewsFeed replyTo;

    @OneToMany(mappedBy="replyTo", cascade=CascadeType.ALL)
    private List<NewsFeed> replies = new ArrayList<NewsFeed>();

    public void addReply(NewsFeed reply){        
       replies.add(reply);
       reply.setReplyTo(this);
    }

    public void removeReply(NewsFeed reply){
       replies.remove(reply);
    }
} 

Так что вы можете думать так. Каждый фид может иметь List ответов, которые также имеют тип NewsFeed. Теперь мне очень легко удалить исходный канал и вернуть обновленный список. Все, что мне нужно сделать после удаления, это.

feeds = scholarEJB.findAllFeed();  //This will query the db and return updated list

Но у меня проблема при попытке удалить replies и получении обновленного списка обратно. Итак, вот как я удаляю replies. Внутри моего управляемого JSF бина у меня есть

//Before invoke this method, I have the value of originalFeed, and deletedFeed set.
//These original feeds are display inside a p:dataTable X, and the replies are
//displayed inside p:dataTable Y which is inside X. So when I click the delete button
//I know which feed I want to delete, and if it is the replies, I will know
//which one is its original post
public void deleteFeed(){
    if(this.deletedFeed != null){
        scholarEJB.deleteFeeds(this.deletedFeed); 
        if(this.originalFeed != null){
            //Since the originalFeed is not null, this is the `replies`
            //that I want to delete
            scholarEJB.removeReply(this.originalFeed, this.deletedFeed);
        }
        feeds = scholarEJB.findAllFeed();
    }        
}

Тогда внутри моего EJB scholarEJB, у меня есть

public void removeReply(NewsFeed feed, NewsFeed reply){
    feed = em.merge(feed);
    comment.removeReply(reply);
    em.persist(comment);
}

public void deleteFeeds(NewsFeed e){
    e = em.find(NewsFeed.class, e.getId());
    em.remove(e);
    em.getEntityManagerFactory().getCache().evict(NewsFeed.class); //Like fdreger suggested
}

Когда я выхожу, сущность (ответ) корректно удаляется из базы данных, но внутри списка feeds, ссылка на этот reply все еще там. Только когда я выйду и снова войду в систему, ответ исчезнет.

Ответы [ 2 ]

6 голосов
/ 31 декабря 2010

То, что вы написали правильно, запрос должен работать (и на самом деле так, как это обычно делается), поэтому проблема должна быть в другом месте.Например, если вы удаляете сущность любым другим способом, кроме метода удаления, она все равно может находиться в кэше 2-го уровня.Или, возможно, запрос не происходит вообще из-за какой-то маленькой ошибки?


Обновление : После прочтения новой версии исходного вопроса (со всеми новыми источниками и разъяснениями оEclipselink) Я сделал небольшой тест, и это - действительно - проблема с кешем второго уровня.Немного странно, и, возможно, это ошибка или недостаточно конкретный угловой случай.Чтобы исправить это, удалите комментарии из кэша:

// this goes after em.remove(e)
em.getEntityManagerFactory().getCache().evict(Comment.class);

Вы также можете попробовать удалить только родитель удаленной сущности (существует перегруженная версия evict).

Uhmpf.Может быть, кто-то с большим уличным кредитом (BalusC? :-) должен поменять теги на этом посте.Оказалось, это не имеет ничего общего с JSF.

3 голосов
/ 04 января 2011

Когда вы удаляете объект, вы должны удалить все ссылки на этот объект перед его удалением.Если вы этого не сделаете, вы можете получить ошибку ограничения или устаревшие данные в контексте постоянства или в кеше 2-го уровня.

При удалении канала сначала удалите его из ответов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...