java嵌套Hibernate实体
我正在创建一个处理办公室事务的SpringJPA(PostgresSQL&;H2)服务。我可以有一个独立的办公室,也可以有一个母公司(公司)和子公司(远程)办公室。办公室有一个地址和员工名单(可以属于多个办公室)。我正在努力设计,非常感谢您能提供的任何帮助
我的表目前处于H2中,用于测试/dev,因此表上没有任何引用完整性
这让我怀疑我的模型是否可以改进。有没有更好的方法来实现这种递归/嵌套关系
更新 基于jfneis的优秀反馈,我现在有了以下方法:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "OfficeType")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "officeId")
public abstract class Office {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "officeId", updatable = false, nullable = false)
private long officeId;
@Column
private String name;
@Column
private String ein;
@Column
@Temporal(TemporalType.DATE)
private Date startDate;
@Column
@Temporal(TemporalType.DATE)
private Date endDate;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "addressId", nullable = false)
private Address address;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Employee> employees = new ArrayList<>();
}
以及公司办事处:
@Entity(name = "CorporateOffice")
@DiscriminatorValue("Corporate")
public class CorporateOffice extends Office {
@Column
private String url;
}
远程办公室:
@Entity(name = "RemoteOffice")
@DiscriminatorValue("Remote")
public class RemoteOffice extends Office {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "corporateOfficeId")
private Office corporateOffice;
}
如果我理解正确,这两种办公室类型都将存储在“office”表中,并有一列指示它是哪种类型
启动时,我正在植入一些测试数据,以便进一步了解发生了什么:
@Component
@Transactional
public class SeedOffices {
@Autowired
private OfficeRepository officeRepository;
@PostConstruct
public void seedOffices() {
CorporateOffice corporate = new CorporateOffice();
corporate.setName("World Domination Corp");
corporate.setUrl("www.corporationsownstheworld.com");
corporate.setStartDate(new Date());
Address corpAddr = new Address();
corpAddr.setAddressLine1("corp line 1");
corpAddr.setCity("Denver");
corporate.setEin("123456789");
corporate.setAddress(corpAddr);
officeRepository.save(corporate);
RemoteOffice office1 = new RemoteOffice();
office1.setStartDate(new Date());
Address remote1Addr = new Address();
remote1Addr.setAddressLine1("remote 1 line 1");
remote1Addr.setCity("Cheyanne");
office1.setAddress(remote1Addr);
officeRepository.save(office1);
office1.setCorporateOffice(corporate);
RemoteOffice office2 = new RemoteOffice();
Address remote2Addr = new Address();
remote2Addr.setAddressLine1("remote 2 line 1");
remote2Addr.setCity("Calumet");
office2.setAddress(remote2Addr);
officeRepository.save(office2);
office2.setCorporateOffice(corporate);
}
}
# 1 楼答案
这是一个带有主观答案的设计问题(这不是应该回答的答案)
不管怎样:我不喜欢单间课。对于两种不同的行为,只有一个类:公司办公室(可以有远程办公室)和远程办公室(可以有父办公室)
在这两点中保留引用符合您的业务需求,但我的建议是:拥有一个抽象类Office,具有公共属性,以及两个子类CorporateOffice和RemoteOffice,它们每个都处理所需的属性
可以使用单表策略将两者映射到同一个表中。关于JPA子类化策略的一篇非常好的文章,请看this article
编辑:回答关于RemoteOffice映射的第二个问题:
我认为您的RemoteOffice映射是错误的。你宣称corporateOffice是一个@OneToMany,但实际上是一个@manytone关系,不是吗?请在此字段中测试@ManyToOne+@JoinColumn,以检查是否解决了您的问题