如何使用JPA注释Map <Entity,INTEGER>?

Moi*_*nGK 5 java hibernate jpa hashmap

我有这张地图:

Map<Owner, Integer> ownerSharesMap = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

我知道如何在地图上HashMap@OneToMany,有一个基本类型为重点的关系,但我GOOGLE了很多,并没有找到一个方法来映射上面HashMap使用JPA.我看到两个选择:

将我HashMap改为:(其中uuid是关键列Owner)

Map<UUID, Integer> ownerIdSharesMap = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

或者创建一个这样的类:

public class Share{
  int count;
  Owner owner
}
Run Code Online (Sandbox Code Playgroud)

然后坚持这个集合:

Set<Share> shares;
Run Code Online (Sandbox Code Playgroud)

你有什么建议?有没有办法用JPA注释第一个Map,还是应该使用后面的解决方案?

请注意,在我的项目中,查询性能是主要问题,但我也想要干净的OOD.

谢谢.

Ish*_*Ish 11

这在JPA中是可能的.

地图集合中的值不是实体,因此您需要使用它进行映射@ElementCollection.

您的映射可以很简单,如下所示:

@ElementCollection
private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();
Run Code Online (Sandbox Code Playgroud)

虽然,您可以指定将存储值的集合表.使用@CollectionTable注释,您可以指定集合表的名称以及连接列.

@ElementCollection
@CollectionTable(name="OWNER_SHARES",
    joinColumns=@JoinColumn(name="SHARE_ID"))
private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();
Run Code Online (Sandbox Code Playgroud)

如果@CollectionTable未指定,则表名将默认为引用实体的名称,附加下划线和包含元素集合的实体属性的名称.在我们的例子中,这将是SHARE_OWNERSHARESMAP.连接列默认值类似于引用实体的名称,附加下划线和实体表的主键列的名称.

您可以使用@Column注释,指定集合表中哪个列所在的地图集合表的整数值.如果未指定,则默认为OWNERSHARESMAP.

@ElementCollection
@CollectionTable(name = "OWNER_SHARES", joinColumns = @JoinColumn(name = "SHARE_ID") )
@Column(name="SHARE_AMOUNT")
private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();
Run Code Online (Sandbox Code Playgroud)

按实体键入时,并非实体的所有属性都将存储在集合表中.它只是将要存储的实体的主键.为此,我们将在集合表中添加一个列来存储映射的键,这是Owner实体主键的外键.要覆盖此列的名称,您可以使用@MapKeyJoinColumn.

@ElementCollection
@CollectionTable(name="OWNER_SHARES", joinColumns=@JoinColumn(name="SHARE_ID"))
@Column(name="SHARE_AMOUNT")
@MapKeyJoinColumn(name="OWNER_KEY")
private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();
Run Code Online (Sandbox Code Playgroud)

如果未指定@MapKeyJoinColumn,则默认列名称将是元素集合属性的名称,并附加字符串"_KEY".所以在我们的例子中,这将是OWNERSHARESMAP_KEY.

以下是您的实体在代码中的外观示例:

@Entity
@Table(name="OWNER")
public class Owner {

    @Id
    @Column(name="OWNER_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer id;
...
}

@Entity
@Table(name = "SHARE")
public class Share {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "SHARE_ID")
    private Integer id;

    @ElementCollection
    @CollectionTable(name = "OWNER_SHARES", joinColumns = @JoinColumn(name = "SHARE_ID") )
    @Column(name="SHARE_AMOUNT")
    @MapKeyJoinColumn(name = "OWNER_KEY")
    private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();
...
}
Run Code Online (Sandbox Code Playgroud)

这是一个持久化实体及其集合的示例代码:

    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();

    Owner owner1 = new Owner();
    Owner owner2 = new Owner();

    em.persist(owner1);
    em.persist(owner2);

    Share share = new Share();
    share.getOwnerSharesMap().put(owner1, 20);
    share.getOwnerSharesMap().put(owner2, 40);

    em.persist(share);

    em.getTransaction().commit();
Run Code Online (Sandbox Code Playgroud)

以下是Hibernate在MySQL中生成模式的方法:

Hibernate: 
    create table OWNER (
        OWNER_ID integer not null auto_increment,
        primary key (OWNER_ID)
    )
Hibernate: 
    create table OWNER_SHARES (
        SHARE_ID integer not null,
        SHARE_AMOUNT integer,
        OWNER_KEY integer not null,
        primary key (SHARE_ID, OWNER_KEY)
    )
Hibernate: 
    create table SHARE (
        SHARE_ID integer not null auto_increment,
        primary key (SHARE_ID)
    )
Hibernate: 
    alter table OWNER_SHARES 
        add constraint FK_th03t34g0d8hj7hmhppaa9juk 
        foreign key (OWNER_KEY) 
        references OWNER (OWNER_ID)
Hibernate: 
    alter table OWNER_SHARES 
        add constraint FK_smwhicxpq0ydqan5jn1p3goom 
        foreign key (SHARE_ID) 
        references SHARE (SHARE_ID)
Run Code Online (Sandbox Code Playgroud)

以下是表格中数据的外观:

在此输入图像描述

您将在我的GitHub 仓库中看到此实现的示例.