如何在 Map<String, Embeddable> 上定义 MapKey 列名

Posted

技术标签:

【中文标题】如何在 Map<String, Embeddable> 上定义 MapKey 列名【英文标题】:How to define MapKey column name on Map<String, Embeddable> 【发布时间】:2017-11-02 12:52:16 【问题描述】:

短版:我正在尝试创建一个:

@ElementCollection
private Map<String, Item> items;

,其中Item@Embeddable,并且能够为映射的键定义在Item 表中创建的列名。休眠版本:5.0.12.Final

完整说明: 以下是重现我的问题的简化示例。 我的出发点是List@Embeddable

@Entity
public class Root 
    @Id
    private Long code;   

    private String value;    

    @ElementCollection
    private Set<Item> items;

@Embeddable
public class Item 
    private String keyValue;    
    private String otherValue;

通过这个映射,hibernate 会创建以下表格:

create table root (
    code int8 not null,
    value varchar(255),
    primary key (code)
);

create table root_items (
    root_code int8 not null,
    key_value varchar(255),
    other_value varchar(255)
);

alter table root_items 
    add constraint FK1o7au7f9ccr8144vyfgsr194v 
    foreign key (root_code) 
    references root;

到目前为止一切顺利。接下来,我尝试将List 转换为Map 并使用Item.keyValue 作为地图的键:

@Entity
public class Root 
    @Id
    private Long code;

    private String value;

    @ElementCollection
    private Map<String, Item> items;

@Embeddable
public class Item 
    private String otherValue;

它有效,但在root_items 表中,地图的键列始终称为items_key,我无法找到如何将此名称强制为key_value

我尝试了以下替代方案:

@ElementCollection
@MapKeyJoinColumn(name = "keyValue")
private Map<String, Item> items;


/* @MapKey doesn't work at all. 
    org.hibernate.AnnotationException: Associated class not found: com.demo.Item
        at org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:116)
*/
@ElementCollection
@MapKey(name = "keyValue")
private Map<String, Item> items;

@ElementCollection
@CollectionTable(joinColumns = @JoinColumn(name = "code"))
@MapKeyJoinColumn(name = "keyValue")
private Map<String, Item> items;

@ElementCollection
@JoinColumn(name = "keyValue")
private Map<String, Item> items;

@ElementCollection
@CollectionTable(joinColumns = @JoinColumn(name = "code"))
@MapKeyJoinColumn(name = "keyValue")
@Column(name = "keyValue")
private Map<String, Item> items;

但列名总是生成为items_key:

create table root_items (
    code int8 not null,
    other_value varchar(255),
    items_key varchar(255) not null,
    primary key (code, items_key)
);

我也尝试了上述所有组合,将 keyValue 保留在 Item 中,但我只得到一个额外的列:

create table root_items (
    code int8 not null,
    key_value varchar(255),
    other_value varchar(255),
    items_key varchar(255) not null,
    primary key (code, items_key)
);

我发现了类似的问题,但没有解决我的问题:

@ElementCollection with Map<Entity, Embeddable> where Entity is a field of the Embeddable

Key & value column name overrides when mapping java.util.Map with JPA annotations

是否有强制列名称为某个自定义值?

编辑 1: 我发现如果地图键是@Embeddable,那么我可以实现它。 但我认为这不是实现这一目标的有效解决方案。我想保留地图键为String

@Entity
public class Root 
    @Id
    private Long code;

    private String value;

    @ElementCollection
    private Map<ItemKey, Item> items;

@Embeddable
public class ItemKey 
    private String keyValue;

当键是String 时,是否有强制列名称为某个自定义值?

【问题讨论】:

【参考方案1】:

终于找到了。就这么简单:

@Entity
public class Root 
    @Id
    private Long code;

    private String value;

    @ElementCollection
    @MapKeyColumn(name = "keyValue")
    private Map<String, Item> items;

我留下答案,以防它可以帮助像我一样迷茫的另一个人。:P

【讨论】:

以上是关于如何在 Map<String, Embeddable> 上定义 MapKey 列名的主要内容,如果未能解决你的问题,请参考以下文章

SWIG 如何在 Python 中包装 map<string,string>?

如何在 java springs 中注入 Map<String, List>?

如何将map<string list<>>转换成城map<string,object>

Java:如何使用 Map<String,String> 在文本中填充占位符?

如何在 Map<String, Embeddable> 上定义 MapKey 列名

如何在颤动中将 Map<String, List<object>> 保存在 sharedPreferences 中?