【发布时间】:2018-01-16 05:47:13
【问题描述】:
为了更好的理解,我想实现这个:
注意:买方可能没有 ExternalAccount,但卖方必须有。我已经/尝试过的:
买家类:
@Entity
public class Buyer extends User {
@OneToOne(optional=true, cascade= {CascadeType.MERGE})
@JoinColumn(nullable=true)
private ExternalAccount externalAccount;
//getters and setters
}
卖家类别:
@Entity
public class Seller extends User {
@OneToOne(optional=false, cascade= {CascadeType.MERGE})
@MapsId
@JoinColumn(nullable=false)
private ExternalAccount externalAccount;
//getters and setters and other properties
}
ExternalAccount 类:
@Entity
public class ExternalAccount {
@Id
@PrimaryKeyJoinColumn
private Long id;
//getters and setters
}
我正在将 Spring Data JPA 与 Spring Boot 一起使用,我希望这样做:
如果没有买家相关但 ExternalAccount 存在(与卖家相关联),则关联它。
如果没有卖方相关但 ExternalAccount 存在(与买方关联),则关联它。
如果不存在 ExternalAccount,则在保存买家/卖家时,创建 ExternalAccount。
我可以使用CascadeType.MERGE 实现类似的行为(在阅读了很多 Stackoverflow 帖子之后),但使用它不尊重@OneToOne 映射。它允许创建许多与同一个 ExternalAccount 相关的买家。
- 我创建了一个带有数据库测试的 github 项目来重现该问题。
https://github.com/ralphavalon/jpa-mapping
在那里,我有我的示例休息控制器(MappingController):
//Creating buyer example
@RequestMapping(value = "/newBuyer", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Object newBuyer() {
Buyer buyer = new Buyer();
buyer.setBirthdate(LocalDateTime.now());
buyer.setEmail("buyer@email.com");
buyer.setName("Buyer Name");
ExternalAccount external = new ExternalAccount();
external.setId(123L);
buyer.setExternalAccount(external);
buyerDao.save(buyer);
return buyer;
}
//Creating seller example
@RequestMapping(value = "/newSeller", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Object newSeller() {
Seller seller = new Seller();
seller.setBirthdate(LocalDateTime.now());
seller.setEmail("seller@email.com");
seller.setName("Seller Name");
ExternalAccount external = new ExternalAccount();
external.setId(123L);
seller.setExternalAccount(external);
sellerDao.save(seller);
return seller;
}
当我第一次调用/newBuyer 时,它会保存。现在,如果我在调用/newBuyer 之后调用/newSeller,它会返回:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PRIMARY KEY ON PUBLIC.EXTERNAL_ACCOUNT(ID)"; SQL statement:
insert into external_account (id) values (?) [23505-196]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.EXTERNAL_ACCOUNT(ID)"; SQL statement:
insert into external_account (id) values (?) [23505-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.196.jar:1.4.196]
【问题讨论】:
-
如果将 externalAccount 关系移动到 User 类会怎样? (它应该可以为空,因为买家可能没有帐户)
-
那么理论上我可以在没有 ExternalAccount 的情况下拥有卖方......这可能是我的出路,但我想要更接近这种方法的东西。它在语义上是正确的。
标签: java jpa spring-boot spring-data spring-data-jpa