如何注释Map< Entity,INTEGER>与JPA? [英] How to annotate Map<Entity,INTEGER> with JPA?

查看:109
本文介绍了如何注释Map< Entity,INTEGER>与JPA?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这张图:

 地图< Owner,Integer> ownerSharesMap = new HashMap<>(); 

我知道如何将 HashMap @OneToMany 关系有一个原始类型作为键,但我搜索了很多,并没有找到一种方法来映射上面的 HashMap 与JPA。
我看到两个选项:

将我的 HashMap 更改为:(其中uuid是所有者的关键字段)

 映射< UUID,Integer> ownerIdSharesMap = new HashMap<>(); 


创建一个这样的类:

  public class Share {
int count;
所有者所有者
}

然后坚持这个设置:

 设置<共享>分享; 

你有什么建议?有没有办法用JPA注释第一个Map或者我应该使用后来的解决方案?注意,在我的项目中,查询性能是主要关心的问题,但我希望清理OOD



谢谢。

解决方案

这在JPA中是可行的。

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



您的映射可以这样简单:

  @ElementCollection 
私人地图<所有者,整数> ownerSharesMap = new HashMap< Owner,Integer>();

尽管您可以指定存储值的集合表。使用 @CollectionTable 注释,您可以指定集合表的名称以及连接列。

  @ElementCollection 
@CollectionTable(name =OWNER_SHARES,
joinColumns = @ JoinColumn(name =SHARE_ID))
私人地图< Owner,Integer> ownerSharesMap = new HashMap< Owner,Integer>();

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



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

  @ElementCollection 
@CollectionTable(name =OWNER_SHARES,joinColumns = @JoinColumn(name =SHARE_ID))
@Column(name =SHARE_AMOUNT)
私人地图< Owner,Integer> ownerSharesMap = new HashMap< Owner,Integer>();

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

  @ElementCollection 
@CollectionTable(name =OWNER_SHARES,joinColumns = @ JoinColumn(name =SHARE_ID))
@Column(name =SHARE_AMOUNT)
@MapKeyJoinColumn(name = OWNER_KEY)
私人地图<所有者,整数> ownerSharesMap = new HashMap< Owner,Integer>();

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



下面是你的实体在代码中的样子:

  @Entity 
@Table(name =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;
$ b $ @ElementCollection
@CollectionTable(name =OWNER_SHARES,joinColumns = @JoinColumn(name =SHARE_ID))
@Column(name =SHARE_AMOUNT)
@MapKeyJoinColumn(name =OWNER_KEY)
私人地图< Owner,Integer> ownerSharesMap = new HashMap< Owner,Integer>();
...
}

下面是一个示例代码,集合:

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

所有者owner1 =新所有者();
所有者owner2 =新所有者();

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

股份=新股();
share.getOwnerSharesMap()。put(owner1,20);
share.getOwnerSharesMap()。put(owner2,40);

em.persist(share);

em.getTransaction()。commit();

以下是Hibernate如何在MySQL中生成模式:

  Hibernate:
创建表OWNER(
OWNER_ID integer不为null auto_increment,
主键(OWNER_ID)

Hibernate:
创建表OWNER_SHARES(
SHARE_ID integer not null,
SHARE_AMOUNT integer,
OWNER_KEY integer not null,
主键(SHARE_ID,OWNER_KEY)

Hibernate:
create table SHARE(
SHARE_ID integer not null auto_increment,
primary key(SHARE_ID)

Hibernate:
alter表OWNER_SHARES
添加约束FK_th03t34g0d8hj7hmhppaa9juk
外键(OWNER_KEY)
引用OWNER(OWNER_ID)
Hibernate:
alter table OWNER_SHARES
添加约束FK_smwhicxpq0ydqan5jn1p3goom
外键(SHARE_ID)
引用SHAR E(SHARE_ID)

以下是数据在您的表格中的样子:



你会在我的GitHub中看到这个实现的例子 repo


I have this map:

Map<Owner, Integer> ownerSharesMap = new HashMap<>();

I know how to map a HashMap with @OneToMany relation that has a primitive type as key, but I googled a lot and didn't find a way to map the above HashMap with JPA. I see two options though:

to change my HashMap to this: (in which the uuid is the key column of Owner)

Map<UUID, Integer> ownerIdSharesMap = new HashMap<>();

or create a class like this :

public class Share{
  int count;
  Owner owner
}

then persist this Set:

Set<Share> shares;

what do you suggest? is there a way to annotate first Map with JPA or should I use the later solutions?

Note that in my project, querying performance is the main concern but I want clean OOD too.

Thanks.

解决方案

This is possible in JPA.

The values in your map collection is not an entity, therefore you need to map it using @ElementCollection.

Your mapping can be simple as this:

@ElementCollection
private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();

Although, you can specify a collection table where the values will be stored. Using @CollectionTable annotation you can specify the name of the collection table as well as the join column.

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

If @CollectionTable is not specified, the table name will default to the name of the referencing entity, appended with an underscore and the name of the entity attribute that contains the element collection. In our example, this will be SHARE_OWNERSHARESMAP. The join column default is similarly the name of the referencing entity, appended with an underscore and the name of the primary key column of the entity table.

You can use @Column annotation, to specify which column in the collection table where the integer values of the map collection table. If not specified, this will default to OWNERSHARESMAP.

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

When keying by entity, not all properties of the entity will be stored in the collection table. It is only the primary key of the entity that will be stored. For this we will have an additional column in our collection table to store the key of your map, that is a foreign key to the Owner entity's primary key. To override the name of this column, you can use @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>();

If @MapKeyJoinColumn is not specified, then the default column name of will be the name of element collection attribute, appended with the string "_KEY". So in our example, this will be OWNERSHARESMAP_KEY.

Here's a sample of how your entities will look like in code:

@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>();
...
}

Here's a sample code persisting the entities and their collections:

    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();

Here's how Hibernate generated the schema in 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)

Here's how data will look like in your tables:

You'll see a sample of this implementation in my GitHub repo.

这篇关于如何注释Map&lt; Entity,INTEGER&gt;与JPA?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆