Поле переключателя Spring JPA из-за ошибки AJAX: StaleObjectStateException - PullRequest
0 голосов
/ 17 ноября 2011
@RequestMapping(value = "/document/togglevisible/{docId}")
public void toggleImageVisible(@PathVariable Integer docId) {
    Document doc = Document.findDocument(docId);
    if (doc.getVisible() == null) {
        doc.setVisible(1);
    } else {
        doc.setVisible(null);
    }
    doc.merge();
}

Я нажимаю на это с помощью ajax-вызова, когда значение флажка меняется:

$.get('/document/togglevisible/' + $(this).attr('data'));

Когда я нажимаю этот URL через браузер, он просто блестяще переключает поле в моей базе данных,никаких проблем вообще.

Когда я нажимаю на него из этого вызова ajax, это сомнительно, делает это или нет.Копаясь в Firebug, чтобы посмотреть на реальный ответ, я вижу, как Спринг выдает это сообщение:

org.hibernate.StaleObjectStateException: Row was updated or deleted by 
another transaction (or unsaved-value mapping was incorrect)

Никогда не слышал о таких вещах, и Google не сильно помогает.Есть ли что-то, что мне нужно сделать после моего merge() вызова для завершения транзакции или что-то в этом роде?Я никогда не включал преднамеренно транзакции (или, может быть, отключал автоматическую фиксацию).

1 Ответ

1 голос
/ 17 ноября 2011

Я понял это. Это не имеет ничего общего с Spring JPA.

В функции javascript, где я заполняю список документов (с их флажком для запуска этого переключения видимости), я говорю:

if (window.Docs.length > 0) {
    $('.mediaVisibilityToggle').live('change', function () {
        $.get("/document/togglevisible/" + $(this).attr('data-rel'));
    });
}

Видите, что .live там? Это говорит jQuery связывать это событие и сохранять его привязанным ко всем изменениям DOM. Поэтому, когда я действительно изменяю DOM и перечисляю документы, связанные с другим родительским объектом, я строю их макет и вызываю live AGAIN для этого класса селектора, в результате чего получаются ДВЕ привязки. Таким образом, каждая кнопка запускает свой вызов ajax столько раз, сколько я перерисовал эту часть страницы. Нет es bueno.

Я изменил его на:

$('.mediaVisibilityToggle').unbind('change');

window.Docs.each( function(item) {
    // do my thing to clear that element and redraw my list of documents
});
if (window.Docs.length > 0) {
    $('.mediaVisibilityToggle').bind('change', function () {
        $.get("/mavenmanagement/admin/document/togglevisible/" + $(this).attr('data-rel'));
    });
}       

Возможно, я мог бы просто перевести мой .live вызов в глобальную одноразовую область где-то, но это было похоже на лучший способ контролировать, что к чему, с точки зрения моих событий. Так что теперь каждый .mediaVisibilityToggle флажок привязан только один раз к своему событию изменения, переключение, кажется, работает безупречно, и все счастливы.

...