当前位置: 首页 > 面试题库 >

如何使用JPA保留两个实体

赫连彬炳
2023-03-14
问题内容

我在Web应用程序中使用了JPA,但我想不出如何持久化彼此相关的两个新实体。这里是一个例子:

这是两个实体

+ ----------------- + + -------------------- +
| 消费者| | 个人资料图片|
+ ----------------- + + -------------------- +
| id(PK)| --- | ConsumerId(PPK + FK)|
| 用户名| | 网址|
+ ----------------- + + -------------------- +

消费者 有一个 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建议,一个问题是缺少id
ProfilePicture 表(我用的是 Consumer.id 外国和初级)..

这些表现在看起来像这样:

+ ----------------- + + -------------------- +
| 消费者| | 个人资料图片|
+ ----------------- + + -------------------- +
| id(PK)| _ | id(PK)|
| 用户名| \ _ | ConsumerId(FK)|
+ ----------------- + | 网址|
                      + -------------------- +

然后,艾伦·海伊(AlanHay)告诉我,
始终封装对关系的添加/删除,然后可以确保正确性 ,我这样做:

消费者.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;
}


 类似资料:
  • 问题内容: 我需要处理一个CSV文件,并且对于每个记录(行)都保留一个实体。现在,我这样做: 该方法基本上只是一个调用。CSV文件中大约有20,000个实体(行)。这是一种有效的方法吗?似乎很慢。使用会更好吗?这个解决方案有任何缺陷吗? 编辑 这是一个漫长的过程(超过400秒)和我都尝试的解决方案,与和。两者花费的时间大致相同(459s与443s)。问题是,像这样一个接一个地保存实体是否最佳。据我

  • 问题内容: 我试图在使用UUID作为主键的PostgreSQL中保留一个实体。我尝试将其持久保存为普通的UUID: 有了以上,我得到这个错误: 我也尝试将UUID保留为byte []无济于事: 如果删除@Lob,我得到的错误与上面发布的错误相同。但是使用@Lob时,错误会稍微更改为: 无法完成如此简单的操作,我感到非常难过! 我正在将Hibernate 4.1.3.Final与PostgreSQL

  • 问题内容: 在我当前的项目中,我正在使用没有JPA批注的第三方库。 如何使用JPA和外部映射持久化该库中的对象? 问题答案: 检查这个和这个。简而言之: 创造 跟随(阅读) 您不必手动映射每列-只需提供一些细节(即集合和ID)。假定所有字段都是列(如果映射了类)。如果没有集合,则可以使用如下所示的内容: 请注意,指定时不需要完全限定的名称。 如果您想要的文件名称不同于,则可以通过以下方式指定该文件

  • 问题内容: 有没有办法使用NHibernate将枚举持久化到数据库?那有一张代码表和枚举中每个值的名称。 我想保留没有实体的枚举,但仍然具有从所有其他引用实体到枚举的表的外键(枚举的int表示形式)。 问题答案: 你们为什么把这个复杂化呢?真的很简单。 映射如下所示: 该模型属性如下所示: 枚举看起来像这样: NHibernate将自动解决所有问题。为什么键入比您需要的更多???

  • 问题内容: 我已经开始使用推荐的广告,并从移走了。我无法重新粘合在一起的一件事是使用持久性Cookie存储。我想简单地将自定义cookie处理程序/管理器附加到我的连接中以存储cookie。Android文档并不是很有帮助,因为它将Cookie主题分为两行。 我以前使用过LoopJ ,效果很好。 关于如何在Android中设置可以附加到我的自动保存和检索cookie 的持久性cookie存储的想法

  • 问题内容: 我的应用程序的Web UI层中有一个JPA实体实例。我想随时知道此实体是否已经保存在数据库中或仅存在于用户会话中。 它将在业务层中,我将使用entitymanager.contains(Entity)方法,但是在我的UI层中,我认为我需要一个额外的属性来指示实体是否已保存。如何实施?我目前正在考虑以下选择: 由数据库设置默认值的JPA属性,但是每次更新后是否会强制进行新的读取? 在我的