在多对多单向映射中持久化枚举集

Persisting set of Enums in a many-to-many unidirectional mapping(在多对多单向映射中持久化枚举集)
本文介绍了在多对多单向映射中持久化枚举集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在使用带有注释的 Hibernate 3.5.2-FINAL 来指定我的持久性映射.我正在努力为应用程序和一组平台之间的关系建模.每个应用程序都可用于一组平台.

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.

从我所做的所有阅读和搜索中,我认为我需要将平台枚举类作为实体持久化,并有一个连接表来表示多对多关系.我希望关系在对象级别是单向的,也就是说,我希望能够获取给定应用程序的平台列表,但我不需要找出给定平台的应用程序列表.

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.

这是我的简化模型类:

@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...
}

当我运行 Hibernate 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);

我希望在 Platform 表中创建适当的行,即为 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. 有没有更好的方法来模拟我想做的事情,例如使用 Enum 合适吗?
  2. 如果我的模型没问题,如何正确持久化所有对象?

我已经为此苦苦挣扎了好几个小时,并尝试重新创建上面的所有代码,但它可能不完整和/或不准确.我希望有人会指出一些明显的事情!

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!

推荐答案

你应该决定你的Platform是否是一个entity.

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

如果是实体,则不能是enum,因为可能的平台列表存储在数据库中,而不是应用程序中.它应该是带有 @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 表,也没有多对多关系.在这种情况下,您可以将一组 Platform 表示为带有位标志的整数字段,或者表示为简单的一对多关系.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)   
);

enum Platform 没有注释.

这篇关于在多对多单向映射中持久化枚举集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How to send data to COM PORT using JAVA?(如何使用 JAVA 向 COM PORT 发送数据?)
How to make a report page direction to change to quot;rtlquot;?(如何使报表页面方向更改为“rtl?)
Use cyrillic .properties file in eclipse project(在 Eclipse 项目中使用西里尔文 .properties 文件)
Is there any way to detect an RTL language in Java?(有没有办法在 Java 中检测 RTL 语言?)
How to load resource bundle messages from DB in Java?(如何在 Java 中从 DB 加载资源包消息?)
How do I change the default locale settings in Java to make them consistent?(如何更改 Java 中的默认语言环境设置以使其保持一致?)