感谢您的帮助,我认为结合 crizzis 和最近 Jens 的建议,我实现了这个 JPA。
@Data
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "address_type", discriminatorType = DiscriminatorType.STRING)
@Table(name = "address")
@TypeDef(name = UUID_CUSTOM_TYPE_NAME, typeClass = com.example.onetoone.domain.entity.UUIDCustomType.class, defaultForType = UUID.class)
public class AddressEntity
{
@Id
private UUID uuid;
private String address1;
private String city;
private String zip;
}
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@DiscriminatorValue("HOME")
public class HomeAddressEntity extends AddressEntity
{
@OneToOne(mappedBy = "homeAddress", fetch = FetchType.LAZY)
private PersonEntity personHome;
}
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@DiscriminatorValue("WORK")
public class WorkAddressEntity extends AddressEntity
{
@OneToOne(mappedBy = "workAddress", fetch = FetchType.LAZY)
private PersonEntity personWork;
}
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@DiscriminatorValue("INCIDENT")
public class IncidentAddressEntity extends AddressEntity
{
@OneToOne(mappedBy = "incidentAddress", fetch = FetchType.LAZY)
private IncidentEntity incident;
}
@Data
@Entity
@Table(name = "person")
@TypeDef(name = UUIDCustomType.UUID_CUSTOM_TYPE_NAME, typeClass = com.example.onetoone.domain.entity.UUIDCustomType.class, defaultForType = UUID.class)
public class PersonEntity
{
@Id
private UUID uuid;
private String name;
@OneToOne(cascade = CascadeType.ALL)
private HomeAddressEntity homeAddress;
@OneToOne(cascade = CascadeType.ALL)
private WorkAddressEntity workAddress;
}
@Data
@Entity
@Table(name = "incident")
@TypeDef(name = UUIDCustomType.UUID_CUSTOM_TYPE_NAME, typeClass = UUIDCustomType.class, defaultForType = UUID.class)
public class IncidentEntity
{
@Id
private UUID uuid;
private String name;
@OneToOne(cascade = CascadeType.ALL)
private IncidentAddressEntity incidentAddress;
}
UUID 类型 def 定义如下,以防万一有人也需要它
public class UUIDCustomType extends AbstractSingleColumnStandardBasicType<UUID> implements LiteralType<UUID>
{
private static final long serialVersionUID = -540308541695243812L;
public static final String UUID_CUSTOM_TYPE_NAME = "uuid-custom";
public UUIDCustomType()
{
// https://stackoverflow.com/questions/42559938/hibernate-uuid-with-postgresql-and-sql-server
super(VarcharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE);
}
@Override
public String getName()
{
return UUID_CUSTOM_TYPE_NAME;
}
@Override
public String objectToSQLString(UUID value, Dialect dialect) throws Exception
{
return StringType.INSTANCE.objectToSQLString(value.toString(), dialect);
}
}
这会在 MySQL 数据库中生成以下 DDL
CREATE TABLE `address` (
`address_type` varchar(31) NOT NULL,
`uuid` varchar(255) NOT NULL,
`address1` varchar(255) DEFAULT NULL,
`city` varchar(255) DEFAULT NULL,
`zip` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uuid`)
)
CREATE TABLE `person` (
`uuid` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`home_address_uuid` varchar(255) DEFAULT NULL,
`work_address_uuid` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uuid`),
KEY `FKoqa1ado547ntt2lc6ppx1lvr4` (`home_address_uuid`),
KEY `FKjc3ayqtduyx0l342uu9ti32hl` (`work_address_uuid`)
)
CREATE TABLE `incident` (
`uuid` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`incident_address_uuid` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uuid`),
KEY `FKosj0m7i6beq7ijwh68tjpfaa7` (`incident_address_uuid`)
)
alter table incident add constraint FKosj0m7i6beq7ijwh68tjpfaa7 foreign key (incident_address_uuid) references address (uuid)
alter table person add constraint FKoqa1ado547ntt2lc6ppx1lvr4 foreign key (home_address_uuid) references address (uuid)
alter table person add constraint FKjc3ayqtduyx0l342uu9ti32hl foreign key (work_address_uuid) references address (uuid)