【问题标题】:How to map oneToone and OneToMany relationship between 3 entities?如何映射 3 个实体之间的 oneToone 和 OneToMany 关系?
【发布时间】:2018-10-21 17:32:48
【问题描述】:

我正在尝试在 JPA 中编程这种关系,但似乎在这里迷失了。 这是我的 ER 模型描述。 我有一个Customer,其中一个有一个Depot,而这个Depot 包含股份(股票)。 所以这就是我的想法。 每个Customer 都有一个Depot,即(有关系)1:1,一个仓库可以包含更多的股份(股票)。仓库 --> 共享 (1:m)

我有以下代码。

客户.java

@Entity
@NamedQuery(name = "Customer.getAll", query = "SELECT c FROM Customer c") 
public class Customer implements Serializable {
    private static final long serialVersionUID = 101L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id; //todo: for standard way of defining primary key

    @NotNull
    private String username;

    @NotNull
    private String firstName;

    @NotNull
    private String lastName;


    @OneToOne
    @JoinColumn(name="depot_id", nullable=false, updatable=false)
    private Depot depot;


    public Customer() {
        super();
    }

}

Depot.java

@Entity
public class Depot  implements Serializable{
    private static final long serialVersionUID = 102L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    /*@Column(name = "id", updatable = false, nullable = false)*/
    @JoinColumn(name = "customer_id")
    private Long id;


    @OneToMany(mappedBy = "tdepot")
    private List<Share> lshares;

    //todo: Total estimated value in USD
    @Transient
    private BigDecimal totalValue = new BigDecimal(0.0);


    public Depot(){
        super();
    }

    @PostConstruct
    public void init(){
        if(lshares == null){
            lshares = new ArrayList<>();
        }

    }
}

Shares.java

@Entity
public class Share implements Serializable{

    private static final long serialVersionUID = 103L;


    @Id
    protected String symbol;


    @NotNull
    protected String companyName;

    @NotNull
    protected Long floatShares;
    protected BigDecimal lastTradePrice;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Date lastTradeTime;

    @NotNull
    protected String stockExchange;


    @ManyToOne(optional=false)
    @JoinColumn(name="depot_id", nullable=false, updatable=false)
    private Depot tdepot;

    public Share(){
        super();
        lastTradeTime = new Date();
    }
}

使用上面的代码,我什至可以创建并保留一个客户。我是不是做错了映射?

如果我尝试将数据持久保存到上述数据库中,我会收到以下错误消息。 [缩短可读性]

引起:javax.persistence.PersistenceException: org.hibernate.PersistentObjectException:分离的实体传递给 坚持:net.dsfinance.bank.ejb.entity.Customer

With .merge instead of persist

12:48:48,875 警告 [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (默认任务 46)SQL 错误:23502,SQLState:23502 12:48:48,876 错误 [org.hibernate.engine.jdbc.spi.SqlExceptionHelper](默认任务 46) “DEPOT_ID”列不允许为 NULL; SQL 语句:插入 客户(地址、depot_id、名字、姓氏、密码、角色、 用户名,id)值(?,?,?,?,?,?,?,?)[23502-173] 12:48:48,883 信息 [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (默认任务 46)HHH000010:在批次发布时,它仍然包含 JDBC 语句 12:48:48,888 WARN [com.arjuna.ats.arjuna](默认 任务 46) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - 失败 对于 SynchronizationImple

: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: 不能 执行语句 org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692) 在 org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) 在 org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) 在 org.hibernate.jpa.internal.EntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(EntityManagerImpl.java:235) 在 org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2967) 在 org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) 在 org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) 在 org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:316) 在 org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47) 在 org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)

引起:org.hibernate.exception.ConstraintViolationException:可以 不执行语句 org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112) 在 org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207) 在 org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45) 在 org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2897) 在 org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3397) 在 org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456) 在 org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 在 org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) 在 org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) 在 org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) 在 org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) ... 129 更多 原因:org.h2.jdbc.JdbcSQLException: NULL not 允许列“DEPOT_ID”; SQL语句:

这是我在使用entitymanger.persist()的时候,谷歌搜索后,有人建议我应该使用merge,但仍然不允许我将客户添加到数据库中。

我想实现什么: 我想为一个简单的 tradeservice java EE 应用程序创建一个数据库, 拥有仓库的客户。包含购买特定客户的所有股票的仓库。 我如何实现这一目标?谢谢

【问题讨论】:

  • 取决于你需要什么;你到底有什么问题?
  • @HBo 我的问题是如何正确链接实体之间的关系。这样我就可以将数据持久化到数据库中。截至目前我不能。在 Jboss Wildfly 服务器上运行它。
  • 我在想 Depot 和 Customer 之间的关系是错误的,1:m 而不是 1:1。因为 Depot 表应该包含很多不同客户的 Depot 共享信息。
  • 这就是背景很重要的地方(=您的需求)。例如,如果depot 不是很重要,您可以使用和@ElementCollection 注释映射shares 的集合(只是为了避免必须执行customer.getDepot().getShares()。为什么不能运行这个?什么例外,...?
  • @HBo ElementCollection 听起来不错。只是为了切断漫长的道路。但我不知道该怎么做。您能否提供一个解决方案来简化此操作。客户和股份。谢谢。

标签: java jpa entity


【解决方案1】:

由于您没有提供用于持久化实体的代码,因此我不会对此进行详细说明(除非您编辑您的帖子),我将重点介绍解决此类问题的步骤。

首先,尝试简单,然后详细说明:从 Customer 类中删除您的 depot 对象,以确保您的 Id 生成策略正常工作。如果没有,您需要先修复它,具体取决于您的数据库。你需要能够持久化一个简单的Customer

一旦您可以保留客户,请向其添加 depot(就像现在一样),而不是其 shares 集合。与以前相同的步骤,直到您可以持久化客户及其 Depot。

最后,添加shares 集合,就像现在一样。 IMO,因为我不熟悉 @PostConstruct 注释,所以我将其删除并替换为普通的旧集合初始化:

private List<Share> lshares = new ArrayList<>();

如果以上都不起作用,那显然不再是映射问题了!

【讨论】:

  • 谢谢,试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
相关资源
最近更新 更多