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

Java 在多对多单向映射中持久化枚举集,java,hibernate,jpa,persistence,annotations,Java,Hibernate,Jpa,Persistence,Annotations,我正在使用Hibernate 3.5.2-FINAL和注释来指定我的持久性映射。我正在努力为应用程序和一组平台之间的关系建模。每个应用程序都可用于一组平台 从我所做的所有阅读和搜索中,我认为我需要将平台枚举类作为一个实体进行持久化,并需要一个连接表来表示多对多关系。我希望关系在对象级别是单向的,也就是说,我希望能够获得给定应用程序的平台列表,但我不需要找到给定平台的应用程序列表 以下是我的简化模型类: @Entity @Table(name = "TBL_PLATFORM") public en

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

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

以下是我的简化模型类:

@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...
}
相应的外键也将从此表创建到应用程序表和平台表。到目前为止还不错

我遇到的一个问题是,当我尝试持久化应用程序对象时:

Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);
不知何故,当我尝试持久化应用程序时,平台集没有被持久化。级联注释应该会解决这个问题,但我不知道出了什么问题

因此,我的问题是:

  • 是否有更好的方法来建模我想做的事情,例如使用枚举是否合适
  • 如果我的模型正常,我如何正确地保存所有对象

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

    您应该决定您的
    平台
    是否为实体

    如果它是一个实体,则不能是
    枚举
    ,因为可能的平台列表存储在数据库中,而不是应用程序中。它应该是一个带有
    @Entity
    注释的常规类,您将拥有一个正常的多对多关系

    如果它不是一个实体,那么您就不需要
    TBL_PLATFORM
    表,也不需要多对多关系。在这种情况下,您可以将一组
    平台
    表示为带位标志的整数字段,或者表示为简单的一对多关系。JPA 2.0通过
    @ElementCollection
    简化了后一种情况:

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

    enum Platform
    无注释。

    在实体上使用下面的映射即可。假设我们有:

    public enum TestEnum { A, B }
    
    然后在实体类中:

    @ElementCollection(targetClass = TestEnum.class)
    @CollectionTable(
            name = "yourJoinTable", 
            joinColumns = @JoinColumn(name = "YourEntityId")
    )
    @Column(name = "EnumId")
    private final Set<TestEnum> enumSet= new HashSet<>();
    
    @ElementCollection(targetClass=TestEnum.class)
    @收集表(
    name=“yourJoinTable”,
    joinColumns=@JoinColumn(name=“YourEntityId”)
    )
    @列(name=“EnumId”)
    私有最终集enumSet=新HashSet();
    
    以下示例显示了当模块是实体而语言是枚举时的情况

    @Entity
    public class Module {
    
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
    
      private String libelle;
    
      @ElementCollection(targetClass = Langue.class, fetch = FetchType.EAGER)
      @CollectionTable(name = "link_module_langue",
                joinColumns = @JoinColumn(name = "module_id", referencedColumnName = "id"))
      @Enumerated(EnumType.STRING)
      @Column(name = "langue")
      private Set<Langue> langues;
    } 
    public enum Langue {
      FRANCAIS, ANGLAIS, ESPAGNOLE
    }
    

    NB:Langue不是一个实体,也不会有自己的表。

    我使用了Hibernate的旧版本来生成模式。通过以下操作,我将依赖项设置为3.5.3-FINAL,“org.hibernate.MappingException:无法确定:java.util.set的类型”消失了。我遵循了您建议的@ElementCollection方法,使用了一个普通的非实体枚举,现在Set被映射到一个联接表。而且,通过在属性上设置@Enumerated,我可以设置枚举值是作为整数还是字符串存储在数据库中。@axtavt我在那里附加了一个赏金,你能帮我一下吗。。急需帮助。@axtavt能否在帖子中添加原则表“TBL_应用程序”的结构?Thnx
    public enum TestEnum { A, B }
    
    @ElementCollection(targetClass = TestEnum.class)
    @CollectionTable(
            name = "yourJoinTable", 
            joinColumns = @JoinColumn(name = "YourEntityId")
    )
    @Column(name = "EnumId")
    private final Set<TestEnum> enumSet= new HashSet<>();
    
    @Entity
    public class Module {
    
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
    
      private String libelle;
    
      @ElementCollection(targetClass = Langue.class, fetch = FetchType.EAGER)
      @CollectionTable(name = "link_module_langue",
                joinColumns = @JoinColumn(name = "module_id", referencedColumnName = "id"))
      @Enumerated(EnumType.STRING)
      @Column(name = "langue")
      private Set<Langue> langues;
    } 
    public enum Langue {
      FRANCAIS, ANGLAIS, ESPAGNOLE
    }
    
    CREATE TABLE `link_module_langue` (
      `module_id` BIGINT(20) NOT NULL,
      `langue` VARCHAR(45) NOT NULL,
      PRIMARY KEY (`module_id`, `langue`),
      CONSTRAINT `module_fk`
        FOREIGN KEY (`module_id`)
        REFERENCES `module` (`id`)
        ON DELETE CASCADE
        ON UPDATE CASCADE);