2012-02-28 24 views
12

Tôi đang sử dụng JPA2 với thực hiện EclipseLinkmapping @ManyToOne thất bại trong việc tiết kiệm cha mẹ ID

! [Cấu trúc bảng đơn giản] [1]

Dưới đây là hai bảng mà tôi cố gắng để lập bản đồ và Chú thích JPA.

public class Story implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    Integer id; 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column (name="DATE_CREATED") 
    Date dateCreated; 
    String title; 
    String description; 
    @Column(name="AUTHOR_ID") 
    Integer authorId; 
    @Column(name="COUNTRY_ID") 
    Integer countryId; 
    private String reviews; 

    @OneToMany(mappedBy = "story", cascade=CascadeType.ALL) 
    private List<Tip> tipList; 
} 

public class Tip implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private Integer id; 
    private String description; 
    private Integer vote; 

    @ManyToOne (cascade=CascadeType.ALL) 
    @JoinColumn(name="STORY_ID", referencedColumnName="ID") 
    private Story story; 
} 

Là một ví dụ đơn giản tôi muốn tồn tại một câu chuyện và một số câu chuyện lời khuyên trong cùng một giao dịch có liên quan. Dưới đây là phần mã mà không rằng:

Story newStory = new Story(title, body, ...); 

EntityTransaction transaction = em.getTransaction().begin(); 
    boolean completed = storyService.create(newStory); 
    //The tips are saved as a List<String>. This methods creates the needed List<Tip> from the Strings 
    List<Tip> tips = TipUtil.getTipList(tipList); 
    newStory.setTipList(tips) 
transaction.commit(); 

Tôi không có lỗi và tất cả các đối tượng được tiếp tục tồn tại cơ sở dữ liệu. Vấn đề là trong bảng mẹo trường story_id luôn là NULL. Tôi có thể tưởng tượng rằng JPA không thể lấy số id mới từ bảng câu chuyện. Cách tiếp cận chính xác ở đây là gì?

LE

Trong tình trạng hiện tại của mã, Tip thực thể đang tồn nhưng ID đất nước vẫn null.

Trả lời

6

Với JPA, bạn nên luôn cập nhật mối quan hệ ở cả hai bên trong mối quan hệ hai hướng. Điều này là để đảm bảo rằng dữ liệu nhất quán trong lớp ứng dụng của bạn và không có gì để làm với cơ sở dữ liệu.

Tuy nhiên, bạn bắt buộc phải cập nhật phần sở hữu của mối quan hệ trong mối quan hệ hai chiều.

Vì vậy, thiết lập/không thiết

story.setTipList(tips) 

là tùy thuộc vào bạn. Nhưng nếu bạn muốn các thay đổi để phản ánh đúng trong DB thì bạn phải gọi số

tip.setStory(story) 

Tip là bên sở hữu ở đây, theo mã của bạn. Mã của bạn trông không đầy đủ đối với tôi. Lý do là,

  • pháp nhân được trả lại bởi storyService.create(newStory) được quản lý chứ không phải newStory. Vì vậy, chỉ cần đặt newStory.setTipList(tips) sẽ không cập nhật db
5

Vì bạn cần cập nhật câu chuyện liên kết gốc trong mỗi con bạn.

Cách thực hiện của nó là tạo phương thức addTip (Mẹo mẹo) trong lớp Story của bạn.

Phương pháp này không:

tip.setStory(this); 
tipList.add(tip); 

Nếu bạn không cần phải tiếp cận bedirectional, bạn có thể loại bỏ các lĩnh vực trong câu chuyện Mẹo và nó sẽ giải quyết vấn đề của bạn

+1

Tôi tự hỏi nếu không có cách nào tự động hơn để thực hiện việc này. Hơn nữa, tôi thực sự không nghĩ rằng việc xóa trường câu chuyện trong Mẹo sẽ là một ý tưởng thông minh, bởi vì theo cách này, anh ta cần phải loại bỏ '@PrimaryKeyJoinColumn (name =" STORY_ID ", referencedColumnName =" ID ") ', để lại JPA không có đầu mối về cách nó sẽ làm cho tham gia. Đây chỉ là những gì tôi hiểu từ đọc một chút về chủ đề này. Vui lòng cho tôi biết nếu tôi sai. – Dragos

+0

Ebean có giải pháp tự động cho giải pháp này, nhưng việc triển khai JPA không cung cấp giải pháp tự động. – Palesz

0

Bạn không nên sử dụng PrimaryKeyJoinColumn, chỉ JoinColumn, nhưng có lớp học hoàn chỉnh của bạn sẽ giúp đưa ra một câu trả lời nhất định.

PrimaryKeyJoinColumn sẽ chỉ được sử dụng nếu story_id cũng là id của Mẹo (không có id trong Mẹo) và có bản đồ cơ bản trùng lặp cho nó. Nó hiếm khi được sử dụng và không được yêu cầu trong JPA 2.0 nữa vì ánh xạ id trùng lặp không còn cần thiết nữa.

+0

Xin chào! Cảm ơn bạn đã phản hồi! Tôi đã cập nhật câu hỏi của mình. Tôi đã thêm tất cả các thuộc tính thực thể và các thay đổi đã diễn ra sau khi thay đổi chú thích '@ PrimaryKeyJoinColumn'. Tôi hy vọng nó rõ ràng hơn bây giờ. – Ionut

1

Tháo

@column (name = "STORY_ID") tin Integer storyId;

Bạn đã khai báo nó trong @JoinColumn (name = "STORY_ID", referencedColumnName = "ID")

Đó là lý do tại sao bạn đang nhận được lỗi Nhiều ánh xạ có thể ghi tồn tại cho trường [tip.STORY_ID]

+0

Xin cảm ơn! Thật vậy, không có lỗi nào khác nhưng các thực thể 'Tip' không được tiếp tục thêm – Ionut

+0

Tùy thuộc vào việc thực hiện, trong mối quan hệ hai chiều, bạn phải đặt cả hai cách của mối quan hệ (tôi không chắc liệu trong eclipselink có giống như vậy hay không) đáng để thử). Vì vậy, hãy thử đặt newStory cho từng mẹo của các mẹo trong danh sách. Ngoài ra, dòng "boolean completed = storyService.create (newStory);" nó sẽ là logic hơn để đặt nó ngay trước transaction.commit; – Pau

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