簡體   English   中英

如何使用JPA保留兩個實體

[英]How to persist two entities with JPA

我在我的Web應用程序中使用了JPA,但我不知道如何持久化彼此相關的兩個新實體。 這里是一個例子:

這是兩個實體

+-----------------+   +--------------------+
|     Consumer    |   |   ProfilePicture   |
+-----------------+   +--------------------+
| id    (PK)      |---| consumerId (PPK+FK)|
| userName        |   | url                |
+-----------------+   +--------------------+

消費者有一個ID和其他一些值。 ProfilePicture使用使用者ID作為其自己的主鍵和外鍵。 (由於沒有使用者,ProfilePicture將不存在,並且並非每個使用者都具有ProfilePicture)

我使用NetBeans生成實體類和會話bean(外觀)。

簡而言之就是這樣

消費者.java

@Entity
@Table(name = "Consumer")
@NamedQueries({...})
public class Consumer implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "userName")
    private String userName;     

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "consumer")
    private ProfilePicture profilePicture;

    /* and all the basic getters and setters */
    (...)
}

ProfilePicture.java

@Entity
@Table(name = "ProfilePicture")
@XmlRootElement
@NamedQueries({...})
public class ProfilePicture implements Serializable {

    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "consumerId")
    private Integer consumerId;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "url")
    private String url;

    @JoinColumn(name = "consumerId", referencedColumnName = "id", insertable = false, updatable = false)
    @OneToOne(optional = false)
    private Consumer consumer;

    /* and all the basic getters and setters */
    (...)
}

因此,當我想用​​他的ProfilePicture創建一個Consumer時 ,我想我會這樣做:

   ProfilePicture profilePicture = new ProfilePicture("http://www.url.to/picture.jpg");  // create the picture object
   Consumer consumer = new Consumer("John Doe"); // create the consumer object

   profilePicture.setConsumer(consumer);        // set the consumer in the picture (so JPA can take care about the relation      
   consumerFacade.create(consumer);             // the facade classes to persist the consumer
   profilePictureFacade.create(profilePicture);  // and when the consumer is persisted (and has an id) persist the picture

我的問題

我幾乎嘗試了每種組合的所有方法,但JPA似乎無法自行鏈接兩個實體。 大多數時候,我會收到如下錯誤:

 EJB5184:A system exception occurred during an invocation on EJB ConsumerFacade, method: public void com.me.db.resources.bean.ConsumerFacade.create(com.mintano.backendclientserver.db.resources.entity.Consumer)
 (...) 
Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.

據我了解的問題,這是因為ProfilePicture不知道使用者的ID,因此實體無法持久。

它唯一有效的方法是,首先持久保存Consumer ,將其id設置為ProfilePicture ,然后持久保存圖片:

   ProfilePicture profilePicture = new ProfilePicture("http://www.url.to/picture.jpg");  // create the picture object
   Consumer consumer = new Consumer("John Doe"); // create the consumer object

   consumerFacade.create(consumer);             // the facade classes to persist the consumer
   profilePicture.setConsumerId(consumer.getId()); // set the consumer's new id in the picture     

   profilePictureFacade.create(profilePicture);  // and when the consumer is persisted (and has an id) persist the picture

但是,這兩個表只是一個示例,自然數據庫要復雜得多,像這樣手動設置id似乎很不靈活,而且我擔心事情會變得過於復雜。 特別是因為我無法將所有實體都保留在一個事務中(這似乎效率很低)。

我做對了嗎? 還是有另一種更標准的方法?

編輯:我的解決方案

正如FTR所建議的那樣,一個問題是ProfilePicture表的id缺失(我將Consumer.id用作外部和主要)。

這些表現在看起來像這樣:

+-----------------+   +--------------------+
|     Consumer    |   |   ProfilePicture   |
+-----------------+   +--------------------+
| id    (PK)      |_  | id (PK)            |
| userName        | \_| consumerId (FK)    |
+-----------------+   | url                |
                      +--------------------+

然后, 艾倫·海伊Alan Hay)告訴我, 始終封裝對關系的添加/刪除,然后可以確保正確性 ,我這樣做了:

消費者.java

public void addProfilePicture(ProfilePicture profilePicture) {
    profilePicture.setConsumerId(this);  
    if (profilePictureCollection == null) {
        this.profilePictureCollection = new ArrayList<>();
    }
    this.profilePictureCollection.add(profilePicture);
}

由於ProfilePicture現在具有其自己的ID,因此它已成為OneToMany關系,因此每個Consumer現在可以擁有許多個人資料圖片。 那不是我最初想要的,但是我可以忍受它:)因此,我不能只為使用者設置一個ProfilePicture,而必須將其添加到Pictures的集合中(如上所述)。

這是我實施的唯一附加方法,現在可以使用。 再次感謝你的幫助!

當持久保留關系的非所有權方的實例(包含“ mappedBy”並且在您的情況下為“消費者”)時,必須始終確保將關系的雙方都設置為具有預期的級聯工作。

您當然應該總是這樣做,以確保您的域模型正確。

Consumer c = new Consumer();
ProfilePicure p = new ProfilePicture();
c.setProfilePicture(p);//see implementation
//persist c

消費者.java

    @Entity
    @Table(name = "Consumer")
    @NamedQueries({...})
    public class Consumer implements Serializable {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Basic(optional = false)
        @Column(name = "id")
        private Integer id;

        @Basic(optional = false)
        @NotNull
        @Size(min = 1, max = 50)
        @Column(name = "userName")
        private String userName;     

        @OneToOne(cascade = CascadeType.ALL, mappedBy = "consumer")
        private ProfilePicture profilePicture;

        public void setProfilePicture(ProfilePicture profilePicture){
            //SET BOTH SIDES OF THE RELATIONSHIP
            this.profilePicture = profilePicture;
            profilePicture.setConsumer(this);
        }
}

始終封裝添加/刪除關系,然后可以確保正確性:

public class Parent{
private Set<Child> children;

public Set<Child> getChildren(){
    return Collections.unmodifiableSet(children); //no direct access:force clients to use add/remove methods
}

public void addChild(Child child){
    child.setParent(this); 
    children.add(child);
}

public class Child(){
    private Parent parent;
}

您可以一次保留一個對象及其子對象。 所以我認為這應該工作:

ProfilePicture profilePicture = new ProfilePicture("http://www.url.to/picture.jpg");  // create the picture object
Consumer consumer = new Consumer("John Doe"); // create the consumer object
consumer.setProfilePicture(profilePicture); 
consumerFacade.create(consumer);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM