jpa Embeddebles-每个实体有多个表,所有实体只有一个表

pbossiut  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(422)

我正在探索能够为多个实体存储特定地址(家庭、工作等)的选项,以及拥有一个包含所有地址的表,可能每个记录都有某种鉴别器。所有表的主键都是uuid。
我使用的是springboot2.3.6和jpa/hibernate。
理想情况下,我希望使用每个实体的命名属性,而不是持有实体的集合,因为这将使dtoMap和更新更容易。
如果共享地址表中的条目中没有输入数据,则每个实体和属性对的值都为空,这对我来说不是问题。
在伪代码中,我希望能够将实体定义为:

@Entity
class Person {
   private Address homeAddress;
   private Address workAddress;
}

@Entity
class Incident {
   private Address incidentLocation;
}

@Entity
class Address {
   private String street;
   private String zip;
}

我研究过使用jpa选项,比如 @Embeddable 我看到的选项是a)每个实体有一个可嵌入的(我想要多个)b)使用 @CollectionTable (我需要特定的命名属性)或c)使用 @AttributeOverride 这意味着表中每个属性的重复列和重命名列。
我也看过 @JoinTable 以及 @OneToMany 但这也是为了使用集合。
我觉得 @Embeddable 是我所需要的,但是需要能够为使用此类型的每个属性(homeaddress、workaddress、incidentlocation)指定一个鉴别器,以便address表中的数据遵循以下格式

id        type      street          zip
=========================================
UUID-1    HOME      1 Main St       30002
UUID-1    WORK      10 North St     30005
UUID-2    INCIDENT  5 West Ave      30008

作为奖励,我还希望(如果可以的话)能够创建一个 JpaRepository<Address> 它允许我独立于父实体查询/更新地址。
有了所有的选择,我想知道是否有人知道是否有一种方法可以实现我想要的,或者我必须走收集路线才能实现这一点?谢谢

lhcgjxsq

lhcgjxsq1#

如果地址与多个元素有关,最好的解决方法是使用一个从任何元素到多个元素的直接关系 Address ,如下所示:

@Entity
class Person {
   @OneToOne
   private Address homeAddress;
   @OneToOne
   private Address workAddress;
}

@Entity
class Incident {
   @OneToOne
   private Address incidentLocation;
}

@Entity
class Address {
   private String street;
   private String zip;
}

如果同一地址被多次使用,也可以使用@manytoone。例如 homeAddress 以及 workAddress 是相同的,并且您不希望有可为null的字段。
在这种情况下,实体 Address 不知道属于哪个实体,但关系的第二方( Person 或者 Incident )知道哪个地址是自己的。在表格中 Person 以及 Incident 将是地址id为的列

3hvapo4f

3hvapo4f2#

只是有一堆财产( homeAddress , workAddress …)每个引用一个 Address 作为一对一的关系,在setter中设置鉴别器。

r8uurelv

r8uurelv3#

多亏了我的帮助,我认为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;
}

以防任何人也需要它

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)

相关问题