2010-05-16 57 views
1

我在使用枚舉類作爲關鍵字的Map上使用正確的hibernate註釋時遇到了問題。這是一個簡化的(而且非常人爲的)例子。什麼是hibernate註釋用於持久作爲一個鍵枚舉類型的地圖?

public class Thing { 
    public String id; 
    public Letter startLetter; 
    public Map<Letter,Double> letterCounts = new HashMap<Letter, Double>(); 
} 


public enum Letter { 
    A, 
    B, 
    C, 
    D 
} 

這裏是東西我目前的註解

@Entity 
public class Thing { 

    @Id 
    public String id; 

    @Enumerated(EnumType.STRING) 
    public Letter startLetter; 

    @CollectionOfElements 
    @JoinTable(name = "Thing_letterFrequencies", joinColumns = @JoinColumn(name = "thingId")) 
    @MapKey(columns = @Column(name = "letter", nullable = false)) 
    @Column(name = "count") 
    public Map<Letter,Double> letterCounts = new HashMap<Letter, Double>(); 

} 

休眠生成以下DDL創建表對我的MySQL數據庫

create table Thing (id varchar(255) not null, startLetter varchar(255), primary key (id)) type=InnoDB; 
create table Thing_letterFrequencies (thingId varchar(255) not null, count double precision, letter tinyblob not null, primary key (thingId, letter)) type=InnoDB; 

注意,Hibernate試圖定義信(我map key)作爲tinyblob,但它將startLetter定義爲varchar(255),即使它們都是枚舉類型Letter。當我嘗試創建我看到下面的錯誤

BLOB/TEXT column 'letter' used in key specification without a key length 

我GOOGLE了這個錯誤的表,看來,MySQL有問題,當您試圖做一個主鍵,這是Hibernate需要的TINYBLOB柱部分使用Thing_letterFrequencies表。所以我寧願按照startLetter的方式將字母映射到varchar(255)。

不幸的是,我一直在使用MapKey註釋一陣子,現在一直無法做到這一點。我也嘗試過@MapKeyManyToMany(targetEntity = Product.class),但沒有成功。任何人都可以告訴我什麼是我的letterCounts地圖正確的註釋,以便休眠將視爲startLetter相同的方式處理letterCounts地圖鍵?

+0

也許你的數據庫有問題。在發佈我的答案(5月16日)之前,我創建了一些測試,並且一切都很順利。 – 2010-05-22 06:36:28

回答

0

我發現了一些適用於https://forum.hibernate.org/viewtopic.php?f=1&t=999270&start=0的東西,雖然它有點醜。如果您認爲字母是com.myexample包這裏是註釋

@CollectionOfElements 
@JoinTable(name = "Thing_letterFrequencies", joinColumns = @JoinColumn(name = "thingId")) 
@MapKey(columns = @Column(name = "letter"), 
    type = @Type(
     type="org.hibernate.type.EnumType", 
     parameters = {@Parameter(name = "enumClass", value="com.myexample.Letter"), @Parameter(name="type", value="12")} 
    )) 
@Column(name = "count") 
public Map<Letter,Double> letterCounts = new HashMap<Letter, Double>(); 

注意@Parameter(名稱=「類型」,值=「12」)顯然,「值12」映射枚舉鍵入一個varchar。希望這可以幫助別人,但如果任何人有一個更清晰的註釋,而不使用像12這樣的神奇數字我想聽到它。

0

如果你使用的Java6,您可以嘗試使用@MapKeyEnumerated(javax.persistence)註釋,而不是@MapKey

@ElementCollection 
    @JoinTable(name = "thing_letter_frequencies", joinColumns = @JoinColumn(name = "thing_id")) 
    @MapKeyEnumerated(EnumType.STRING) 
    @Column(name = "letter_count") 
    public Map<Letter, Double> letterCount = new HashMap<Letter, Double>(); 

UPDATE:

全班代碼(使用項目龍目島)

@Entity 
public class Thing { 

    @Getter 
    @Setter 
    @Id 
    private String id; 

    @Getter 
    @Setter 
    @Enumerated(EnumType.STRING) 
    private Letter startLetter; 

    @Getter 
    @Setter 
    @ElementCollection 
    @JoinTable(name = "thing_letter_frequencies", joinColumns = @JoinColumn(name = "thing_id")) 
    @MapKeyEnumerated(EnumType.STRING) 
    @Column(name = "letter_count") 
    public Map<Letter, Double> letterCount = new HashMap<Letter, Double>(); 
} 

hibernate在MySQL中產生什麼(創建表語句):

CREATE TABLE `thing` (
    `id` VARCHAR(255) NOT NULL, 
    `startLetter` VARCHAR(255) NULL DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
ROW_FORMAT=DEFAULT; 

CREATE TABLE `thing_letter_frequencies` (
    `thing_id` VARCHAR(255) NOT NULL, 
    `letter_count` DOUBLE NULL DEFAULT NULL, 
    `letterCount_KEY` VARCHAR(255) NOT NULL DEFAULT '', 
    PRIMARY KEY (`thing_id`, `letterCount_KEY`), 
    INDEX `FKA0A7775246D72F41` (`thing_id`), 
    CONSTRAINT `FKA0A7775246D72F41` FOREIGN KEY (`thing_id`) REFERENCES `thing` (`id`) 
) 
ENGINE=InnoDB 
ROW_FORMAT=DEFAULT; 
+0

我嘗試了你建議的註釋,並得到了與以前完全相同的錯誤。 (還是)感謝你的建議。 – 2010-05-17 17:24:04