如何使用JPA注释Map ?(How to annotate Map with JPA?)

编程入门 行业动态 更新时间:2024-10-28 14:25:58
如何使用JPA注释Map ?(How to annotate Map with JPA?)

我有这张地图:

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

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

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

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

或者像这样创建一个类:

public class Share{ int count; Owner owner }

然后坚持这套:

Set<Share> shares;

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

请注意,在我的项目中,查询性能是主要关心的问题,但我也希望清理OOD。

谢谢。

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.

最满意答案

这在JPA中是可行的。

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

你的映射可以这样简单:

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

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

@ElementCollection @CollectionTable(name="OWNER_SHARES", joinColumns=@JoinColumn(name="SHARE_ID")) private Map<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") private Map<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") private Map<Owner, Integer> ownerSharesMap = new HashMap<Owner, Integer>();

如果未指定@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>(); ... }

以下是一个示例代码,其中保留了实体及其集合:

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

下面是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)

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

在这里输入图像描述

你会在我的GitHub 仓库中看到这个实现的例子。

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:

enter image description here

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

更多推荐

本文发布于:2023-07-15 05:33:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1110708.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:注释   如何使用   annotate   JPA   Map

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!