简体   繁体   中英

Mapping a java.util.Map in a Entity with Hibernate

In my current spring project, I am looking a way to map a field like in one of my entities:

private Map attribute;

where the type of the key should be a two-caracters string representing a language, and the type for the value should be a string with about 128Kb-length.

with this, I should be be able to use something like this for store data for this attribute in my database:

<select name="..." multiple="multiple">
    <option value="..."> ... </option>
</select>

<textarea name="..."> ... </textarea>

where in the select I choose one language and type in the textarea I insert a text in the selected language.

In my views, implemented with thymeleaf, I want read the text associated to the user's language.

Anyone can tell me if there is a way, using Hibernate, to map this kind od field?

You can do what duckstep suggests but if you want finer grained control over where the mapping table lies you can use the following annotations.

@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name = "FOO_TABLE", joinColumns = @JoinColumn(name = "fooId"))
@MapKeyColumn(name="mapKey")
@Column(name = "mapValue")
private Map<String, String> fooMap = new HashMap<String, String>();

This means that FOO_TABLE will have 4 columns. An ID column as the primary key, mapKey ( varchar(255) ), mapValue ( varchar(255) ), and fooId as the foreign key.

The annotations applied to the map do the following things:

@ElementCollection(fetch=FetchType.EAGER) - Tells Hibernate that you have a collection of elements (String's), and that these elements should always be eagerly fetched. Apply this if you never want your map to be null. On the other hand if fetching the map is an expensive query or the map is going to be particularly large and you don't always need it, set FetchType.LAZY instead. (See here for an in depth idea of EAGER vs LAZY fetching)

@CollectionTable - Tells Hibernate that your collection values are stored on a table. The table name is specified by the name parameter, and the FK column is specified using the @JoinColumn annotation.

@MapKeyColumn - Points to the column that contains the values for the map key's.

@Column - Points to the column that contains the values for the map value's.

You can easily change the values for @MapKeyColumn and @Column if you want to.

Note that if you are finding that you are not returning distinct values in the map try adding @Fetch(FetchMode.SUBSELECT) to the collection. This indicates that Hibernate should subselect the map values rather than trying to join them to your parent.

@OneToMany
private Map<String, String> attribute;

Add @MapKeyColumn and/or @Column if your column names don't match JPA's defaults. Use generics for your Map ( Map<String, String> ) so you don't have to specify the types manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM