坚持以枚举为键的地图和对象列表为值的地图

时间:2019-05-23 07:15:09

标签: jpa

我正在努力保留地图。首先是我的数据库设计: enter image description here 我有一个侧面装载机,最多可以有5个不同的容器大小。 ContainerSize定义为枚举。对于每个容器大小,都有多个比例条目。因此,这是一个 1到5到n 的关系。

当前,我用以下实体表示此设计:

@Entity
@Table(name = "sideloader")
public class SideloaderEntity {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "currency")
    private Currency currency;

    // TODO
    private Map<ContainerSize, SideloaderContainersizeEntity> scalesPerContainerSize;

@Entity
@Table(name = "sideloader_containersize")
public class SideloaderContainersizeEntity {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    //TODO
    private List<SideloaderScaleEntity> scales;

@Entity
@Table(name = "sideloader_containersize_scale")
public class SideloaderScaleEntity {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long scaleId;

    @Column(name = "upper_bound_distance_km")
    private int upperBoundDistanceKm;

    ...

现在,我被卡住了。我不确定是否可以将此映射到我现有的数据库布局。而且我不知道我需要确切使用哪些注释。我已经阅读了一些有关“如何持久化地图”的文章,但是这些文章总是在没有现有数据库布局的情况下描述映射。

可以帮我吗?

2 个答案:

答案 0 :(得分:1)

我会尝试通过三个步骤来实现您的结果:

  1. 尝试使用SideloaderEntity映射SideloaderContainersizeEntityList之间的关系,暂时跳过SideloaderContainersizeEntitySideloaderScaleEntity之间的关系。为此,用private Map<ContainerSize, SideloaderContainersizeEntity> scalesPerContainerSize;替换@OneToMany(mappedBy = "sideloaderEntity") private List<SideloaderContainersizeEntity> sideloaderContainersizeEntities;就足够了,其中sideloaderEntity@ManyToOne private SideloaderEntity sideloaderEntity的{​​{1}}字段。
  2. 尝试将SideloaderContainersizeEntity替换为List:将Map替换为private List<SideloaderContainersizeEntity> sideloaderContainersizeEntities;,其中@MapKey(name = "containerSize") private Map<ContainerSize, SideloaderContainersizeEntity> scalesPerContainerSize;是{{ 1}}。
  3. containerSizeprivate ContainerSize containerSize之间的关系添加为SideloaderContainersizeEntity

答案 1 :(得分:0)

借助同事和@Smutje的帖子,我提出了以下解决方案:

@Entity
@Table(name = "sideloader")
public class SideloaderEntity {

    @Column(name = "currency")
    private Currency currency;

    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "sideloader_id", referencedColumnName = "id")
    @MapKey(name = "containerSize")
    private Map<ContainerSize, SideloaderContainersizeEntity> scalesPerContainerSize;

@Entity
@Table(name = "sideloader_containersize")
public class SideloaderContainersizeEntity {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Enumerated(EnumType.STRING)
    @Column(name = "container_size")
    private ContainerSize containerSize;

    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "sideloader_containersize_id", referencedColumnName = "id")
    private List<SideloaderScaleEntity> scales;

@Entity
@Table(name = "sideloader_containersize_scale")
public class SideloaderScaleEntity {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long scaleId;

    @Column(name = "upper_bound_distance_km")
    private int upperBoundDistanceKm;

    ...

我已经测试过使用以下代码对其进行持久化,并且似乎可以正常工作:

@Test
void foo() {

    SideloaderPriceComponent sideloader = new SideloaderPriceComponent();

    SideloaderScaleEntity scale = new SideloaderScaleEntity();
    scale.setUpperBoundDistanceKm(10);

    SideloaderContainersizeEntity containersize = new SideloaderContainersizeEntity();
    containersize.setContainerSize(ContainerSize.FORTY);
    containersize.setScales(Collections.singletonList(scale));

    sideloader.setScalesPerContainerSize(Collections.singletonMap(ContainerSize.FORTY, containersize));

    em.persist(sideloader);
    em.flush();
}