2010-03-14 21 views
68

Tôi cố gắng để chạy mã JPA/EJB cơ bản này:"thực thể tách ra thông qua để tồn tại lỗi" với mã JPA/EJB

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

tôi nhận được lỗi này:

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

Bất kỳ ý tưởng?

Tôi tìm kiếm trên internet và lý do tôi tìm thấy là:

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

Nhưng tôi đã không nhận được nó, những gì tôi sẽ phải thay đổi để lấy mã làm việc?

Trả lời

45

ERD

Giả sử bạn có hai thực thể AlbumPhoto. Album chứa nhiều ảnh, vì vậy đó là mối quan hệ một đến nhiều.

lớp Album

@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>(); 
} 

Ảnh lớp

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

    String photoName; 

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

} 

gì bạn phải làm trước khi kéo dài hoặc hợp nhất là để thiết lập các tài liệu tham khảo Album trong mỗi bức ảnh.

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

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

Đó là cách đính kèm pháp nhân liên quan trước khi bạn duy trì hoặc hợp nhất.

+0

Nếu bạn sử dụng generics, không cần sử dụng "targetEntity = Photo.class" – Rollerball

+0

hi, sau khi đặt đối tượng album thành photo1 nad photo2 ... đối tượng nào chúng ta phải lưu danh sách Ảnh hoặc Album? –

11

tôi có câu trả lời, tôi đã sử dụng:

em.persist(user); 

Tôi đã từng hợp nhất ở vị trí của tồn tại:

em.merge(user); 

Nhưng không biết, tại sao tồn tại không làm việc. : (

+9

đây không phải là giải pháp! –

+0

tôi biết, nhưng điều này làm việc cho tôi. bất kỳ câu trả lời khác ở đây mà làm việc cho bạn? nếu có, thì tôi sẽ rất vui khi chọn nó. – zengr

+4

Nó hoạt động vì đối tượng của bạn được tách ra khỏi phiên ngủ đông hoặc đối tượng là tạm thời nhưng hibernate thấy nó như tách ra bởi vì bạn đã khai báo khóa chính, Với việc sử dụng kết hợp bạn đính kèm đối tượng tot he session lần nữa cho phép bạn cập nhật các đối tượng trong cơ sở dữ liệu; xem: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-detached – Ben

112

Lỗi xảy ra vì ID của đối tượng được đặt. Hibernate phân biệt giữa các đối tượng tạm thời và tách rời và persist chỉ hoạt động với các đối tượng tạm thời. sẽ trở lại với "đối tượng tách ra thông qua để tồn tại" lỗi bạn có thể tìm thêm chi tiết và here

Tuy nhiên, điều này chỉ áp dụng nếu bạn đã xác định khóa chính để được tự động tạo ra:.. nếu lĩnh vực này được cấu hình luôn được đặt thủ công, sau đó mã của bạn hoạt động.

+0

Tôi có đúng về mặt kỹ thuật khi tôi nói, tôi đang sử dụng JPA chứ không phải Hibernate như vậy, tuyên bố trên không nên áp dụng đúng không? Tôi là newbie trong JPA (3 ays là chính xác: P) – zengr

+0

JPA Javadoc của Sun (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html#persist(java.lang .Object)) và của Toplink là chính xác như nhau và đề nghị bạn về mặt kỹ thuật đúng. Tuy nhiên, nó thực sự chứa đựng những gì mà đặc điểm kỹ thuật nói dai dẳng() nên hành xử như thế và thật đáng buồn, tôi không biết đó là gì. –

+0

Giải pháp này làm việc cho tôi. Tôi đã kiên trì một đối tượng, giữ ID được lưu trữ ở đâu đó. Sau đó, tôi muốn ghi đè lên đối tượng hiện có với một giá trị mới, vì vậy tôi đã tạo đối tượng, sao chép ID trở lại và nó sẽ phát sinh khi tôi cố gắng lưu. Cuối cùng, tôi đã phải requery DB (findById), thực hiện các thay đổi, và sau đó kiên trì * rằng * đối tượng. – cs94njw

2

Tôi có vấn đề này và nó được gây ra bởi bộ nhớ cache mức độ thứ hai:

  1. tôi vẫn kiên trì một thực thể sử dụng chế độ ngủ đông
  2. Sau đó, tôi đã xóa hàng được tạo ra từ một quá trình riêng biệt mà không tương tác với mức thứ hai bộ nhớ cache
  3. tôi vẫn kiên trì một thực thể có cùng một định danh (giá trị định danh của tôi là không tự động tạo ra)

do đó, vì bộ nhớ cache đã không vô hiệu, Hib ernate giả định rằng nó đang xử lý một cá thể tách rời của cùng một thực thể.

19

loại bỏ

user.setId(1); 

vì nó là tự động tạo ra trên DB, và tiếp tục với kiên trì lệnh.

4

Tôi biết loại của nó quá muộn và linh hoạt đều có câu trả lời. Nhưng nhiều hơn một chút để thêm vào điều này: khi GenerateType được thiết lập, persist() trên một đối tượng được mong đợi để có được một id được tạo ra.

Nếu có giá trị được đặt thành Id theo người dùng, hibernate coi đó là bản ghi đã lưu và do đó nó được coi là bị tách rời.

nếu id là null - trong tình huống này một con trỏ ngoại lệ null được đưa ra khi các loại là AUTO hoặc SẮC vv trừ id được tạo ra từ một bảng hoặc một sequece, vv

thiết kế: điều này xảy ra khi bảng có thuộc tính bean làm khóa chính. GenerateType chỉ được đặt khi id được tạo tự động. xóa mục này và chèn sẽ hoạt động với id được chỉ định của người dùng. (thiết kế xấu có một thuộc tính được ánh xạ tới trường khóa chính)

4

Ở đây .persist() chỉ sẽ chèn bản ghi. Nếu chúng tôi sử dụng .merge(), nó sẽ kiểm tra có bất kỳ bản ghi nào tồn tại với hiện tại không ID, Nếu nó tồn tại nó sẽ cập nhật nếu không nó sẽ chèn bản ghi mới.

+0

Tôi đã mất rất nhiều thời gian cho đến khi tôi nhận được câu trả lời của bạn. Cảm ơn nhiều! –

7

nếu bạn sử dụng để tạo chiến lược id = GenerationType.AUTO trong pháp nhân của mình.

Thay thế user.setId (1) theo user.setId (null) và sự cố được giải quyết.

1

Nếu bạn đặt id trong cơ sở dữ liệu của bạn là chìa khóa chính và autoincrement, sau đó dòng mã này là sai:

user.setId(1); 

Hãy thử với điều này:

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

Tôi đã thử điều đó và tôi biết nhận được lỗi này: 'thực thể tách rời được chuyển sang tồn tại' – s1ddok

0

Một lý do khác cho rằng lỗi của bạn đối tượng thực thể không triển khai giao diện 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 { 
    // ... 
} 
Các vấn đề liên quan