«Отключенный объект, переданный для сохранения ошибки» с кодом 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
Есть идеи?
- Где ConfigurationGenerateSchemaCreationScript () переместился в Hibernate 5
- JPA 2.0 orphanRemoval = true VS on delete Cascade
- Включение зависимостей Spring в объект EntityListener
- Bypass GeneratedValue в спящем режиме (данные объединить не в db?)
- Связь JPA Hibernate «один-к-одному»
Я ищу в Интернете, и причина, по которой я нашел, была:
Это было вызвано тем, как вы создали объекты, т. Е. Если вы явно задали свойство ID. Исправлено удаление идентификатора.
Но я не понял, что мне нужно изменить, чтобы заставить код работать?
- Отображение столбца PostgreSQL JSON для типа значения Hibernate
- Как просмотреть SQL-запросы, выпущенные JPA?
- Когда должен быть создан / открыт экземпляр EntityManagerFactory?
- JPA EntityManager: зачем использовать persist () над merge ()?
- Получить фактический тип аргумента generic type для абстрактного суперclassа
- аннотация для фильтрации результатов ассоциации @OneToMany
- Решить проблему Liby-Hibernate с помощью hibernate.enable_lazy_load_no_trans
- Спящий режим: создание таблиц Mysql InnoDB вместо MyISAM
Допустим, у вас есть два объекта 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 photos = new HashSet (); }
Фотоclass
@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
завершает, объект отделяется (что будет связано с тем, что ID установлен), он вернет ошибку «отсоединенный объект, прошедший для сохранения». Вы можете найти более подробную информацию здесь и здесь .
Однако это применимо только в том случае, если вы указали, что первичный ключ должен быть сгенерирован автоматически: если поле настроено всегда для установки вручную, тогда ваш код работает.
Удалить
user.setId(1);
потому что он автоматически генерируется в БД и продолжает команду persist.
Я получил ответ, я использовал:
em.persist(user);
Я использовал слияние вместо сохранения:
em.merge(user);
Но не знаю, почему упорство не получилось. 🙁
если вы используете для создания страtagsи id = GenerationType.AUTO
в своей организации.
Заменяет user.setId (1)
на user.setId (null)
, и проблема решена.
Я знаю, что он слишком поздно и уверен, что каждый получил ответ. Но немного больше, чтобы добавить к этому: когда установлен GenerateType, persist () на объекте должен получить генерируемый идентификатор.
Если уже установлено значение Id для пользователя, hibernate рассматривает его как сохраненную запись, и поэтому он рассматривается как отсоединенный.
если id равен null – в этой ситуации исключение с нулевым указателем возникает, когда тип AUTO или IDENTITY и т. д., если идентификатор не генерируется из таблицы или отдельной строки и т. д.
design: это происходит, когда таблица имеет свойство bean как первичный ключ. GenerateType должен быть установлен только тогда, когда идентификатор автогенерируется. удалите это, и вставка должна работать с указанным пользователем идентификатором. (это плохой дизайн, чтобы иметь свойство, отображаемое в поле первичного ключа)
Здесь .persist () будет только вставлять запись. Если мы используем .merge (), он проверит, существует ли какая-либо запись с текущим идентификатором. Если она существует, она будет обновляться, иначе она будет вставлять новую запись.
У меня была эта проблема, и она была вызвана кешем второго уровня:
- Я сохранял объект, использующий hibernate
- Затем я удалил строку, созданную из отдельного процесса, который не взаимодействовал с кешем второго уровня
- Я сохранял другой объект с тем же идентификатором (мои значения идентификатора не генерируются автоматически)
Следовательно, поскольку кеш не был аннулирован, 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 { // ... }