"Thực thể tách rời được chuyển thành lỗi vẫn tồn tại" với mã JPA / EJB


81

Tôi đang cố gắng chạy mã JPA / EJB cơ bản này:

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

Tôi gặp lỗi này:

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

Có ý kiến ​​gì không?

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

Điều này là do cách bạn tạo các đối tượng, tức là Nếu bạn đặt thuộc tính ID rõ ràng. Xóa chỉ định ID đã sửa nó.

Nhưng tôi không hiểu, tôi sẽ phải sửa đổi những gì để mã hoạt động?

Câu trả lời:


50

ERD

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

Lớp anbom

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

Lớp ảnh

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

    String photoName;

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

}

Những gì bạn phải làm trước khi duy trì hoặc hợp nhất là đặt tham chiếu Album trong mỗi ả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 thực thể liên quan trước khi bạn tồn tại hoặc hợp nhất.


2
Nếu bạn sử dụng thuốc chung, không cần sử dụng "targetEntity = Photo.class"
Rollerball

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

129

Lỗi xảy ra do 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à persistchỉ hoạt động với các đối tượng tạm thời. Nếu persistkết luận đối tượng bị tách rời (điều này sẽ xảy ra do ID được đặt), nó sẽ trả về lỗi "đối tượng tách rời được truyền để tồn tại". Bạn có thể tìm thêm thông tin chi tiết tại đâytại đây .

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


Liệu tôi có đúng về mặt kỹ thuật khi nói rằng, tôi đang sử dụng JPA chứ không phải Hibernate, vì vậy câu nói trên không nên áp dụng đúng không? Tôi là người mới trong JPA (chính xác là 3 ays: P)
zengr

JPA Javadoc của Sun ( java.sun.com/javaee/5/docs/api/javax/persistence/… ) và của Toplink hoàn toàn giống nhau và cho thấy bạn đã đúng về mặt kỹ thuật. Tuy nhiên, nó thực sự tóm tắt những gì đặc điểm kỹ thuật cho biết là Kiên trì () sẽ hoạt động như thế nào và thật đáng buồn, tôi không biết đó là gì.
Tomislav Nakic-Alfirevic

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 đè đối tượng hiện có đó bằng một giá trị mới, vì vậy tôi đã tạo đối tượng, sao chép lại ID và nó bị nổ khi tôi cố gắng lưu. Cuối cùng, tôi phải yêu cầu DB (findById), thực hiện các thay đổi và sau đó duy trì đối tượng đó .
cs94njw

24

tẩy

user.setId(1);

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


12

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

em.persist(user);

Tôi đã sử dụng hợp nhất thay cho tồn tại:

em.merge(user);

Nhưng không biết, tại sao kiên trì không hoạt động. :(


11
đây không phải là giải pháp!
Ammar Bozorgvar

1
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 nào khác ở đây phù hợp với 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 ở chế độ ngủ đông xem nó như được tách ra vì bạn đã khai báo khóa chính, Với việc sử dụng hợp nhất, bạn đính kèm đối tượng vào phiên ngủ đông một lần nữa, điều này cho phép bạn cập nhật các đối tượng trong cơ sở dữ liệu của mình ; xem: docs.jboss.org/hibernate/core/3.3/reference/en/html/…
Ben

9

nếu bạn sử dụng để tạo id = GenerationType.AUTOchiến lược trong thực thể của mình.

Thay thế user.setId (1)bằng user.setId (null), và vấn đề được giải quyết.


5

Tôi biết điều đó là quá muộn và mọi người đều có câu trả lời. Nhưng cần thêm một chút nữa vào điều này: khi GenerateType được thiết lập, Kiên trì () trên một đối tượng sẽ nhận được một id được tạo.

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

nếu id là null - trong trường hợp này, ngoại lệ con trỏ null được đưa ra khi kiểu là AUTO hoặc IDENTITY, v.v. trừ khi id được tạo từ bảng hoặc chuỗi ký tự, v.v.

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 phải được đặt chỉ khi id được tạo tự động. loại bỏ điều này và chèn sẽ hoạt động với id người dùng chỉ định. (việc có một thuộc tính được ánh xạ tới trường khóa chính là một thiết kế tồi)


5

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


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

3

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

user.setId(1);

Hãy thử với cái này:

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

Tôi cố gắng điều đó và tôi biết nhận lỗi này:detached entity passed to persist
s1ddok

2

Tôi gặp sự cố này và nguyên nhân là do bộ đệm ẩn cấp thứ hai:

  1. Tôi vẫn duy trì một thực thể sử dụng chế độ ngủ đông
  2. Sau đó, tôi đã xóa hàng được tạo từ một quy trình riêng biệt không tương tác với bộ đệm ẩn cấp hai
  3. Tôi đã duy trì một thực thể khác có cùng số nhận dạng (giá trị số nhận dạng của tôi không được tạo tự động)

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.