一对侧有限选项的多对多映射

时间:2012-10-28 21:12:07

标签: hibernate orm mapping

我正在实现一个模拟电影院控股的Java应用程序。其中一个实体是Film,此实体可以有多个Genres,但显然只有有限数量的Genres。我不确定如何在Hibernate中实现它。

首先,我创建了一个枚举类Genre,并为Film实体提供了Set<Genre> genres = new HashSet<>();属性。

这个问题是Genre在数据库中存储为BLOB,在由Hibernate创建的名为film_genres的表中存储,我无法要求所有电影一个特定的Genre。 (至少在我对Hibernate的有限经验中)。

然后我想我可以在启动时填充数据库,其中Genres类看起来像这样Genre

public class Genre {
    private Integer id;
    private String name;

    private Genre() {}

    public Genre(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    private void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    private void setName(String name) {
        this.name= name;
    }
}

非常基础的课程。但现在说我要向Genre添加Film,我不能这样做:

Film film = new Film("The Terminal");
film.addGenre(new Genre("Drama"));

因为这会为每一部类型剧的电影创造一个新的Genre对象。那么我是否必须首先访问数据库以获取值为“Drama”的Genre对象,然后添加该对象?

如果那是应该做的,那么我仍然想使用这样的枚举:

public enum GenreEnum {
    DRAMA("Drama"),
    ADVENTURE("Adventure"),
    ACTION("Action"),
    ...

    private String value;

    GenreEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

这样做的原因是我可以完全控制进入数据库的初始值的拼写(预填充)和枚举的值,所以我现在可以这样做:

Film film = new Film("The Terminal");
film.addGenre(GenreEnum.DRAMA);

然后在我能做的addGenre方法中:

public void addGenre(GenreEnum ge) {
    Query query = session.createQuery("from Genre g where g.name = " + ge.getValue());
    Genre genre = (Genre)query.list().get(0);
    this.genres.add(genre);
}

我不会把交易代码放在模型中,但我只是把它放在那里以简化。我也意识到串联的使用是不安全的。

这是一个不错的解决方案还是我错过了更简单的方法来实现这个目标?

1 个答案:

答案 0 :(得分:0)

将整个流派作为主键

public enum Genre {
    DRAMA("Drama"),
    ADVENTURE("Adventure"),
    ACTION("Action"),
    ...

    private String value;

    GenreEnum(String value) {
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public String getValue() {
        return value;
    }
}

<compositeId>
  <key-property name="value" />
</compositeId>


Film film = new Film("The Terminal");
film.addGenre(session.load<GenreEnum>(Genre.DRAMA));

// or
for(Genre g : GetAllGenre)
    session.attach(g);

Film film = new Film("The Terminal");
film.addGenre(Genre.DRAMA);

或在枚举中引入固定的ID

public enum Genre {
    DRAMA(1, "Drama"),
    ADVENTURE(2, "Adventure"),
    ACTION(3, "Action"),
    ...

    private int id;
    private String value;

    GenreEnum(int id, String value) {
        this.id = id;
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public String getValue() {
        return value;
    }
}

Film film = new Film("The Terminal");
film.addGenre(session.load<GenreEnum>(Genre.DRAMA.getId()));