java - 如何映射 3 个实体之间的 oneToone 和 OneToMany 关系?
问题描述
我正在尝试在 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();
}
}
仓库.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<>();
}
}
}
分享.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 WARN [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 INFO [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl](默认任务 46)HHH000010:在批处理发布时,它仍然包含 JDBC 语句 12:48:48,888 WARN [com.arjuna.ats.arjuna](默认任务 46) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - SynchronizationImple< 0:ffffc0a80869:-53b30100:5af571b4:4d, org.jboss.as.txn.service.internal.tsr 失败。
:javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:无法在org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert的org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)执行语句(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)internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47) 在 org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47) 在 org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
h2.jdbc.JdbcSQLException:列“DEPOT_ID”不允许为 NULL;SQL 语句:
这是我使用的时候entitymanger.persist()
,谷歌搜索后,有人建议我应该使用merge
但仍然不允许我将客户添加到数据库中。
我想实现什么:我想为一个简单的交易服务 java EE 应用程序创建一个数据库,客户有一个仓库。包含购买特定客户的所有股票的仓库。我如何实现这一目标?谢谢
解决方案
由于您没有提供用于持久化实体的代码,因此我不会详细说明这一点(除非您编辑您的帖子),我将重点介绍解决此类问题的步骤。
首先,尝试简单,然后详细说明:depot
从类中删除您的对象,Customer
以确保您的 Id 生成策略正常工作。如果没有,您需要先修复它,具体取决于您的数据库。你需要能够坚持一个简单的Customer
.
一旦你可以保留一个客户,depot
就添加一个(就像现在一样),而不是它的shares
集合。与以前相同的步骤,直到您可以保留客户及其仓库。
最后,添加shares
集合,就像现在一样。IMO,因为我不熟悉 @PostConstruct 注释,所以我将其删除并替换为普通的旧集合初始化:
private List<Share> lshares = new ArrayList<>();
如果以上都不起作用,那显然不再是映射问题了!
推荐阅读
- java - robovm 和 java SE 兼容性
- graphql - 嵌套查询 - Graphql
- recursion - 什么时候应该使用堆栈将递归函数转换为迭代函数?
- python - 如何创建一列并根据单独的列值用新值填充它
- swift - 如何在swift中显示带有多个错误的错误消息?
- python - Csr 矩阵:如何用 np.nan 而不是 0 替换缺失值?
- javascript - 如何在不编写内联js编码的情况下在onclick方法中传递一个ID
- javascript - 这种情况的最佳动画选项
- flutter - 如何与 ListView 分开显示项目
- centos - RHEL 7.2 yum install openssl-devel 错误