"Отключенный объект, переданный для сохранения ошибки" с кодом JPA/EJB

Я пытаюсь запустить этот базовый код JPA/EJB:

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setId(1);
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

Я получаю эту ошибку:

javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database

Любые идеи?

Я ищу в Интернете, и причина, по которой я нашел, была:

Это было вызвано тем, как вы создали объекты, т.е. если вы явно задали свойство ID. Исправлено удаление идентификатора.

Но я не понял, что мне нужно изменить, чтобы заставить код работать?

Ответ 1

ERD

Скажем, у вас есть два объекта Album и Photo. Альбом содержит много фотографий, поэтому он имеет отношение от одного до многих.

Класс альбома

@Entity
public class Album {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer albumId;

    String albumName;

    @OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
    Set<Photo> photos = new HashSet<Photo>();
}

Класс фотографий

@Entity
public class Photo{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer photo_id;

    String photoName;

    @ManyToOne(targetEntity=Album.class)
    @JoinColumn(name="album_id")
    Album album;

}

Что нужно сделать, прежде чем продолжать или объединить, нужно установить ссылку на альбом в каждой фотографии.

        Album myAlbum = new Album();
        Photo photo1 = new Photo();
        Photo photo2 = new Photo();

        photo1.setAlbum(myAlbum);
        photo2.setAlbum(myAlbum);       

Вот как присоединить связанный объект до того, как вы будете продолжать или сливаться.

Ответ 2

Ошибка возникает из-за того, что установлен идентификатор объекта. Спящий режим различает переходные и отдельные объекты, а persist работает только с переходными объектами. Если persist завершает удаление объекта (что будет связано с тем, что идентификатор установлен), он вернет ошибку "отсоединенный объект, прошедший для сохранения". Вы можете найти более подробную информацию здесь и здесь.

Однако это применимо только в том случае, если вы указали первичный ключ, который должен быть автоматически сгенерирован: если поле настроено всегда на ручной настройку, тогда ваш код работает.

Ответ 3

удалить

user.setId(1);

поскольку он автоматически генерируется на БД, и продолжайте с помощью команды persist.

Ответ 4

Я получил ответ, я использовал:

em.persist(user);

Я использовал слияние вместо persist:

em.merge(user);

Но не знаю, почему упорство не сработало.: (

Ответ 5

если вы используете для создания стратегии id = GenerationType.AUTO в своей сущности.

Заменяет user.setId (1) на user.setId (null), и проблема решена.

Ответ 6

Я знаю, что он слишком поздно и уверен, что каждый получил ответ. Но немного больше, чтобы добавить к этому: когда установлен GenerateType, persist() на объекте должен получить генерируемый идентификатор.

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

если id равен null - в этой ситуации исключение нулевого указателя возникает, когда тип AUTO или IDENTITY и т.д., если идентификатор не генерируется из таблицы или секировки и т.д.

design: это происходит, когда таблица имеет свойство bean в качестве первичного ключа. GenerateType должен быть установлен только тогда, когда идентификатор автогенерируется. удалите это, и вставка должна работать с указанным пользователем идентификатором. (это плохой дизайн, чтобы иметь свойство, отображаемое в поле первичного ключа)

Ответ 7

Здесь .perist() будет только вставлять запись. Если мы используем .merge(), он проверит, существует ли какая-либо запись с текущим идентификатором. Если она существует, она обновится, иначе она будет вставлять новую запись.

Ответ 8

У меня была эта проблема, и она была вызвана кешем второго уровня:

  • Я сохранял объект, использующий hibernate
  • Затем я удалил строку, созданную из отдельного процесса, который не взаимодействовал с кешем второго уровня
  • Я сохранял другой объект с тем же идентификатором (мои значения идентификатора не сгенерированы автоматически)

Следовательно, поскольку кеш не был аннулирован, hibernate предположил, что он имеет дело с отдельным экземпляром того же объекта.

Ответ 9

Если вы установите id в своей базе данных как первичный ключ и автоинкремент, то эта строка кода неверна:

user.setId(1);

Попробуйте следующее:

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

Ответ 10

Другая причина ошибки в том, что объект объекта не реализует интерфейс Serializable

@Entity
@Table(name = OddInstance.objectName, uniqueConstraints = @UniqueConstraint(columnNames = {"alias"}))
@NamedQueries({
    @NamedQuery(name=OddInstance.findByAlias,
            query="from OddInstance where alias = :alias"),
    @NamedQuery(name=OddInstance.findAll,
            query="from OddInstance")
})
public class OddInstance implements Serializable {
    // ...
}