坚持一个多一对多的单向映射设置的枚举 [英] Persisting set of Enums in a many-to-many unidirectional mapping

查看:1448
本文介绍了坚持一个多一对多的单向映射设置的枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Hibernate 3.5.2-决赛中以注释来指定我的坚持映射。我与建模应用程序和一组平台之间的关系挣扎。每个应用程序可用于一组平台。

I'm using Hibernate 3.5.2-FINAL with annotations to specify my persistence mappings. I'm struggling with modelling a relationship between an Application and a set of Platforms. Each application is available for a set of platforms.

从所有的阅读和搜索我做了,我想我需要有平台枚举类被持久化作为一个实体,并有一个连接表重新present许多一对多的关系。我想要的关系是在对象级别,也就是说,我希望能够得到一个给定的应用程序平台的列表单向的,但我并不需要找出应用程序列表对于一个给定的平台。

From all the reading and searching I've done, I think I need to have the platform enum class be persisted as an Entity, and to have a join table to represent the many-to-many relationship. I want the relationship to be unidirectional at the object level, that is, I want to be able to get the list of platforms for a given application, but I don't need to find out the list of applications for a given platform.

下面是我的简化模型类:

Here are my simplified model classes:

@Entity
@Table(name = "TBL_PLATFORM")
public enum Platform {
    Windows,
    Mac,
    Linux,
    Other;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id = null;

    @Column(name = "NAME")
    private String name;

    private DevicePlatform() {
        this.name = toString();
    }

    // Setters and getters for id and name...
}

@Entity
@Table(name = "TBL_APP")
public class Application extends AbstractEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name = "NAME")
    protected String _name;

    @ManyToMany(cascade = javax.persistence.CascadeType.ALL)
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
    @JoinTable(name = "TBL_APP_PLATFORM", 
              joinColumns = @JoinColumn(name = "APP_ID"),
              inverseJoinColumns = @JoinColumn(name = "PLATFORM_ID"))
    @ElementCollection(targetClass=Platform.class)
    protected Set<Platform> _platforms;

    // Setters and getters...
}

当我运行休眠先得用hbm2ddl工具,我看到下面的(我使用MySQL):

When I run the Hibernate hbm2ddl tool, I see the following (I'm using MySQL):

create table TBL_APP_PLATFORM (
    APP_ID bigint not null,
    PLATFORM_ID bigint not null,
    primary key (APP_ID, PLATFORM_ID)
);

适当的外键也从该表中创建应用程序表和平台表。到目前为止好。

The appropriate foreign keys are also created from this table to the application table and platform table. So far so good.

一个问题我运行到是,当我试图坚持一个应用对象:

One problem I'm running into is when I try to persist an application object:

Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);

我想是发生在平台表创建的,即相应的行创建一个行用于Windows和Linux,如果他们不存在。那么,对于新的应用程序的行应创建,然后在表中加入新的应用程序,并在两个平台之间的映射。

What I would like to happen is for the appropriate rows in the Platform table to created, i.e. create a row for Windows and Linux, if they don't already exist. Then, a row for the new application should be created, and then the mapping between the new application and the two platforms in the join table.

一个问题我运行到越来越以下运行时异常:

One issue I'm running into is getting the following runtime exception:

2010-06-30 13:18:09,382 6613126-0 ERROR FlushingEventListener Could not synchronize database state with session org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.model.Platform

不知何故,该平台集不被当我试图坚持应用依然存在。级联注解都应该照顾,但我不知道什么是错的。

Somehow, the platform set is not being persisted when I try to persist the application. The cascade annotations are supposed to take care of that, but I don't know what's wrong.

所以我的问题是:


  1. 有没有更好的方式来建模是我想做的事,例如采用枚举合适?

  2. 如果我的模型是好的,我该如何正确地坚持所有的对象?

我一直在挣扎与此几个小时,我已经试图重新上面的所有code,但它可能是不完整的和/或准确。我希望有人会指出一些明显!

I've been struggling with this for hours, and I've tried to recreate all of the code above, but it might not be complete and/or accurate. I'm hoping someone will point out something obvious!

推荐答案

您应决定是否你的平台实体的或没有。

You should decide whether your Platform is an entity or not.

如果这是一个实体,它不能成为一个枚举的,因为可能的平台列表存储在数据库中,而不是在应用程序。这应该是一个普通班与 @Entity 注释,你将有一个正常的许多一对多的关系。

If it's an entity, it can't be an enum, because list of possible platforms is stored in the database, not in the application. It should be a regular class with @Entity annotation and you will have a normal many-to-many relation.

如果它不是一个实体,那么你不需要 TBL_PLATFORM 表,你没有很多一对多的关系。在这种情况下,您可以重新present一组平台取值要么与位标志整型字段,或作为一个简单的一对多关系。 JPA 2.0使后者情况下,简单的 @ElementCollection

If it isn't an entity, then you don't need TBL_PLATFORM table, and you don't have a many-to-many relation. In this case you can represent a set of Platforms either as an integer field with bit flags, or as a simple one-to-many relation. JPA 2.0 makes the latter case simple with @ElementCollection:

@ElementCollection(targetClass = Platform.class) 
@CollectionTable(name = "TBL_APP_PLATFORM",
    joinColumns = @JoinColumn(name = "APP_ID"))
@Column(name = "PLATFORM_ID")
protected Set<Platform> _platforms; 

-

create table TBL_APP_PLATFORM (   
    APP_ID bigint not null,   
    PLATFORM_ID bigint not null, -- the ordinal number of enum value   
    primary key (APP_ID, PLATFORM_ID)   
);

枚举平台没有标注。

这篇关于坚持一个多一对多的单向映射设置的枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆