1

列挙型クラスをキーとしてマップで使用する適切な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
}

これがThingに関する私の現在の注釈です

@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として定義しようとしますが、両方とも列挙型Letterであっても、startLetterをvarchar(255)として定義していることに注意してください。テーブルを作成しようとすると、次のエラーが表示されます

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

このエラーをグーグルで検索したところ、tinyblob列を主キーの一部にしようとするとMySqlに問題があるようです。これは、休止状態がThing_letterFrequenciesテーブルで行う必要があることです。したがって、startLetterのように、文字をvarchar(255)にマップしたいと思います。

残念ながら、私はしばらくの間MapKeyアノテーションに悩まされていて、これを機能させることができませんでした。@MapKeyManyToMany(targetEntity = Product.class)も試しましたが、成功しませんでした。hibernateがletteCountsマップキーをstartLetterと同じように処理するように、letterCountsマップの正しい注釈を教えてもらえますか?

4

2 に答える 2

0

java6を使用する場合は、@ MapKeyの代わりに@MapKeyEnumerated(javax.persistence)アノテーションを使用してみてください。

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

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 に答える
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 に答える