"отсоединенный объект передан для сохранения ошибки" с кодом 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 явно. Удаление присвоения идентификатора исправило это.




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

1579   10  

10 ответов:

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);       

то есть, как присоединить Связанный объект перед сохранением или слиянием.

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

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

удалить

user.setId(1);

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

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

em.persist(user);

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

em.merge(user);

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

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

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

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

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

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

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

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

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

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

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

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

user.setId(1);

попробуйте с помощью этого:

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

еще одна причина ошибки, которую ваш объект сущности не реализует 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 {
    // ...
}

Comments

    Ничего не найдено.