1

我无法获得正确的休眠注释以在以枚举类为键的 Map 上使用。这是一个简化(并且非常人为)的示例。

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

}

Hibernate 生成以下 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 尝试将 letter(我的映射键)定义为 tinyblob,但是它将 startLetter 定义为 varchar(255),即使两者都是枚举类型 Letter。当我尝试创建表时,我看到以下错误

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

我用谷歌搜索了这个错误,当您尝试将 tinyblob 列作为主键的一部分时,MySql 似乎出现了问题,这是 hibernate 需要对 Thing_letterFrequencies 表执行的操作。所以我宁愿像 startLetter 那样将字母映射到 varchar(255) 。

不幸的是,我已经对 MapKey 注释大惊小怪了一段时间,并且无法完成这项工作。我也试过 @MapKeyManyToMany(targetEntity=Product.class) 没有成功。谁能告诉我 letterCounts 映射的正确注释是什么,以便休眠将 letterCounts 映射键以与 startLetter 相同的方式处理?

4

2 回答 2

0

我发现了一些适用于https://forum.hibernate.org/viewtopic.php?f=1&t=999270&start=0的东西,尽管它有点难看。如果您假设 Letter 在 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(name="type", value="12") 显然“value=12”将枚举类型映射到varchar。希望这对其他人有所帮助,但如果有人在不使用像 12 这样的幻数的情况下有更清晰的注释,我想听听。

于 2010-05-17T19:33:31.130 回答
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>();

更新:

全班代码(使用 Project Lombok)

@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;
于 2010-05-16T03:30:17.700 回答