为了更好地理解,我想实现这个目标:
注意:买方可能没有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相关的买家。
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
时,会保存。现在,如果我在调用/newSeller
后致电/newBuyer
,则会返回此信息:
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]
答案 0 :(得分:0)
我解决了这些变化的问题:
买方类:
@Entity
public class Buyer extends User {
@OneToOne(optional=true, cascade= {CascadeType.MERGE})
@JoinColumn(nullable=true, unique=true)
private ExternalAccount externalAccount;
//getters and setters
}
卖家类:
@Entity
public class Seller extends User {
@OneToOne(optional=false, cascade= {CascadeType.MERGE})
@JoinColumn(nullable=false, unique=true)
private ExternalAccount externalAccount;
//getters and setters
}
ExternalAccount 类:
@Entity
public class ExternalAccount {
@Id
private Long id;
//getters and setters
}
最重要的部分:覆盖Spring Data JPA保存方法以使用entityManager.merge
@Service
public class BuyerService {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public Buyer save(Buyer buyer) {
return entityManager.merge(buyer);
}
}
和SellerService一样。