2013-08-17 23 views
6

tôi sử dụng Spring 3.2.3 và Hibernate 4.2.3 và JDK 7.đối tượng tham chiếu một thể hiện thoáng qua chưa được lưu: làm thế nào để tuôn ra hoặc trả lại lưu đối tượng

Tôi có một thực thể đơn giản:

@Entity 
public class Language { 
    @Id 
    @GeneratedValue 
    private long id; 

    @Column(nullable = false, length = 3, unique = true) 
    private String code; 
} 

tôi lưu một thể hiện của thực thể này sử dụng một lớp chú thích @Service với một @Transactional phương pháp chú thích trong đó sử dụng một DAO giúp tiết kiệm các thực thể với

sessionFactory.getCurrentSession().save(object); 

Sau đó tôi sử dụng d các lưuLanguage tổ chức để tạo EntityX, mà sử dụng nó trong một mối quan hệ ManyToOne ...

lang=new Language(); 
// ... 
languageService.saveLanguage(lang); 
e=new EntityX(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

EntityX được định nghĩa là ...

@Entity 
public class EntityX { 
    @ManyToOne 
    @JoinColumn(nullable = false) 
    private Language language; 
     // ... 
} 

tôi luôn luôn nhận được ngoại lệ

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language 

Tôi cố gắng sử dụng một số định nghĩa tầng trong EntityX ' s liên quan đến Language như được đề xuất trong các bài viết khác, nhưng nó không có hiệu lực.

Nếu tôi tải lại đối tượng đã lưu Language bằng cách tìm số code bằng cách sử dụng truy vấn HQL, thì mọi thứ hoạt động tốt, nhưng nó ở xa 'đẹp'.

Rất tiếc, (các) phương thức save(...) của org.hibernate.Session không trả lại đối tượng đã lưu.

Có ai có ý tưởng nào để giải quyết nó không?

Trả lời

5

là bạn mã trong một phương pháp duy nhất @Transactional?
Nếu không phải là vấn đề có thể là, sau khi bất kỳ cuộc gọi đến phương thức dịch vụ, giao dịch sẽ được cam kết và phiên xóa. Khi bạn cố gắng lưu thực thể, đối tượng ngôn ngữ không được phát hiện trong phiên và được quản lý dưới dạng phiên bản tạm thời và cung cấp lỗi.

Trong trường hợp mã của bạn đang trong một giao dịch, bạn đã thử flush() trước khi lưu thực thể để buộc cửa hàng Hibernate Language vào cơ sở dữ liệu và gán cho nó một mã định danh hợp lệ @Id?

Sau khi tất cả - IMHO - nếu bạn có một sự phụ thuộc từ Entity và Ngôn ngữ lựa chọn tốt nhất là:

@ManyToOne(cascade = CascadeType.ALL) 
private Language language; 

và thay đổi mã của bạn như:

e=new EntityX(); 
Language lang = new Language(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

và bạn không cần phải thực thể tồn tại theo hai bước (ngôn ngữ + thực thể); quản lý ngôn ngữ + thực thể dưới dạng một mục duy nhất

PS: Phương thức save (...) của org.hibernate.Session không trả về đối tượng đã lưu vì đối tượng sẽ giữ nguyên (tham chiếu không thay đổi), chỉ thay đổi thuộc tính đối tượng (ví dụ như đối tượng được đánh dấu là @Id)!

CHỈNH SỬA:
Tạo đối tượng liên tục (session.save() nó có nghĩa là) không dẫn đến việc chèn/cập nhật ngay lập tức; mà không có gợi ý cascade Hibernate nhìn không phát hiện sự phụ thuộc giữa EntityX và ngôn ngữ và không thực hiện một chèn sql của ngôn ngữ trước khi lưu EntityX.
languageService.save (ngôn ngữ) gọi không thực hiện session.flush() vì bạn dưới cùng @Transactional và không có session.commit() no session.flush() được thực hiện và tùy chọn tốt nhất là đối tượng Ngôn ngữ vẫn được đánh dấu là tạm thời.
Bạn có thể thực hiện kiểm tra: trích xuất dịch vụ lưu mã (thực thể ngôn ngữX) và đặt tất cả trong @Transactional và kiểm tra xem Hibernate vẫn cung cấp cho bạn lỗi hay không.
Tùy chọn tốt nhất của tôi vẫn thực hiện lệnh tuôn ra() ở giữa hoặc thay đổi ánh xạ của bạn, không có cách nào khác

+0

Mã này nằm trong một 'Giao dịch' duy nhất. Các phương thức dịch vụ cũng là '@ Transactional' nhưng chúng requries không có giao dịch mới vì vậy tôi cho rằng phương thức hiện có được sử dụng. Tôi đã lưu ngôn ngữ cho riêng mình, bởi vì tôi có một thực thể Ngôn ngữ và nhiều EntityX và mỗi người trong số họ sử dụng cùng một thực thể Ngôn ngữ. – t777

+1

kiểm tra chỉnh sửa của tôi, quá dài để nhận xét. Tôi hy vọng sẽ được rõ ràng, tiếng Anh không phải là ngôn ngữ mẹ đẻ của tôi, xin lỗi –

+0

Hi @LucaBassoRicci, tôi đang gặp vấn đề tương tự nhưng công nghệ của tôi là khác nhau, bạn có thể hãy xem này .. http://stackoverflow.com/questions/28279304/lỗi-khi-tiết kiệm-một-đối tượng-trong-có-nước ngoài-key-đối tượng-tài liệu tham khảo-một-chưa lưu –

2

Thứ nhất, nếu trường code là chìa khóa chính (hoặc bạn đang ít nhất là sử dụng nó như ID chính của bạn cho Hibernate), xác định @ id:

@Id 
@GeneratedValue(generator="assigned") 
@Column(length = 3) 
private String code; 

Không chỉ định một cột ID có thể gây nhầm lẫn Hibernate một chút; mặc dù không báo cho tôi về điều đó.

Nếu save() vẫn không hoạt động sau đó, bạn có thể sử dụng merge():

Language lang = new Language("XYZ"); 
lang = session.merge(lange); 
+0

Tôi rất tiếc. Tôi đã rút ngắn mã của mình quá nhiều. Có một trường ID. Tôi đã thêm nó vào mã của bài đăng của tôi. Tôi đã gặp vấn đề tương tự khi tôi đang sử dụng hợp nhất thay vì lưu. – t777

Các vấn đề liên quan