PersistentObjectException: отдельная сущность передана, чтобы сохраниться - PullRequest
3 голосов
/ 06 октября 2011

В моем приложении я подключен к веб-сокету. Сокет отправляет данные JSON. Когда оно становится доступным, я обрабатываю его на другой работе В каждой работе я конвертирую JSON в модельный объект с помощью GSON. Существует 3 типа моделей, все независимые и с одним общим полем отметки времени в MappedSuperclass. У них нет явного поля id. Я вызываю save для модели и в 1 из 1000 раз выдается «PersistentObjectException: отдельная сущность, переданная для сохранения».

Несколько заданий вызываются из запускаемого задания, которое подключается к веб-сокету. Библиотека, которую я использую, создает отдельную ветку для каждого входящего сообщения. Затем я преобразую поток в задание перед сохранением в базу данных. Я делаю это, потому что в противном случае выдается еще одно исключение PersistentObjectException при изменении идентификатора с 1 на 2 или что-то подобное, если я разрешу исходному потоку вызвать save.

У меня также запущено другое задание, которое одновременно обращается к базе данных. Что может быть не так?

@Override
public void onMessage(final WebSocketMessage message){
        new Job() {
            @Override
            public void doJob() {
                processMessage(message.getText());
            }
        }.now();

}

 public void processMessage(String message) {
        Appointment appointment = new Gson().fromJson(message, Appointment.class);
        appointment.save();
 }

 @Entity
 public class Appointment extends CalendarEvent {
       private String owner;
 }

 @MappedSuperclass
 public abstract class CalendarEvent extends Model {
       private long timestamp;
 }

РЕДАКТИРОВАТЬ: Добавлен пример кода

Ответы [ 2 ]

5 голосов
/ 06 октября 2011

По сути это означает, что EntityManager не будет их больше отслеживать: Это хороший обзор . Как они стали считаться отстраненными, когда вы явно не просили об этом, странно.Но обходной путь может заключаться в использовании "защитного" подхода в вашем методе DAO и merge этих странных случаях;то есть:

public void save (Model possiblyDetachedModel) {

   if (entityManager.contains(possiblyDetachedModel)) {
        entityManager.merge(possiblyDetachedModel);
    } else {
        entityManager.persist(possiblyDetachedModel);
    }
}

Мне это не особо нравится, потому что этого не нужно делать, когда вы persist используете совершенно новые объекты.Возможно, стоит добавить в систему (или отладить, если это вообще возможно) ветку "merge" и действительно осмотреть эти мошеннические объекты - я уверен, что EntityManager может использовать только поле @Id в качестве обнаружениямеханизм ...

0 голосов
/ 06 октября 2011

Я нашел этот обходной путь для работы на данный момент.Возможно, это связано с тем, как взаимодействуют Gson и Jpa.Не уверен ...

public void processMessage(String message) {
        Appointment appointment = new Gson().fromJson(message, Appointment.class);
        //recreate appointment
        appointment = new Appointment(appointment);
        appointment.save();  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...