2010-03-14 2 views
68

Я пытаюсь запустить этот базовый код 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 

Любые идеи?

Я ищу в интернете и почему я нашел:

This was caused by how you created the objects, i.e. If you set the ID property explicitly. Removing ID assignment fixed it.

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

ответ

45

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

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

+0

Если вы используете дженерики, нет необходимости использовать «targetEntity = Photo.class» – Rollerball

+0

привет, после установки объекта альбома на фото 1 над фото2 ... какой предмет нам нужно сохранить список фотографий или альбома? –

11

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

em.persist(user); 

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

em.merge(user); 

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

+9

это не решение! –

+0

Я знаю, но это сработало для меня. любой другой ответ здесь, который сработал для вас? если да, то я буду более чем счастлив выбрать его. – zengr

+4

Это работало, потому что ваш объект был отделен от сеанса спящего режима или объект был временным, но спящий режим считает его отключенным, потому что вы получили объявленный первичный ключ. С помощью слияния вы снова присоединяете объект tot it session, что позволяет обновлять объекты в вашем база данных; см .: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-detached – Ben

112

Ошибка возникает потому, что идентификатор объекта имеет значение. Hibernate различия между переходными и отдельными объектами и persist работает только с временными объектами. Если persist заключает объект отсоединяется (который он будет, потому что ID установлен), его вернет «обособленную объект передается сохраняются» ошибка вы можете найти более подробную информацию и here

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

+0

Буду ли я технически прав, когда я говорю, я использую JPA, а не Hibernate, поэтому, что вышеприведенное заявление не должно применяться правильно? Я новичок в JPA (3 ays, если быть точным: P) – zengr

+0

Sun JPA Javadoc (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html#persist(java.lang .Object)), а Toplink - это то же самое и предложить вам технически правильно. Тем не менее, это действительно сводится к тому, что спецификация говорит persist() должна вести себя как и грустно, я не знаю, что это такое. –

+0

Это решение сработало для меня. Я сохранял объект, сохраняя идентификатор, хранящийся где-то. Затем я хочу перезаписать этот существующий объект с новым значением, поэтому я создал объект, скопировал его обратно, и он взорвался, когда я попытался сохранить. В конце концов, мне пришлось потребовать DB (findById), внести изменения, а затем сохранить * этот * объект. – cs94njw

2

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

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

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

19

удалить

user.setId(1); 

, потому что это автоматически генерировать на БД, и продолжать упорствовать команду.

4

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

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

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

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

4

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

+0

Это стоило мне кучу времени, пока я не получил ваш ответ. Большое спасибо! –

7

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

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

1

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

user.setId(1); 

Попробуйте с этим:

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

Я пробовал это, и я знаю, что получаю эту ошибку: 'Отдельный объект, переданный для сохранения' – s1ddok

0

Другая причина ошибки, что ваш объект объекта не реализует 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 { 
    // ... 
} 
Смежные вопросы