【问题标题】:JPA enumerated entity with ManyToMany relationship具有多对多关系的 JPA 枚举实体
【发布时间】:2017-03-03 21:04:05
【问题描述】:

我有两个具有多对多关系的实体。我的数据库结构:

Document    Status                  Document_Status
╔════╗      ╔════╦══════════╗       ╔═════════════╦═══════════╗
║ id ║      ║ id ║  status  ║       ║ document_id ║ status_id ║
╠════╣      ╠════╬══════════╣       ╠═════════════╬═══════════╣
║  1 ║      ║  1 ║ STORED   ║       ║           1 ║         1 ║
║  2 ║      ║  2 ║ APPROVED ║       ║           2 ║         1 ║
║  3 ║      ╚════╩══════════╝       ║           3 ║         2 ║
╚════╝                              ╚═════════════╩═══════════╝

我想使用枚举作为状态。

public enum Status {
    STORED, APPROVED
}

@Entity
public class Document {

    @Id
    @GeneratedValue
    private long id;

    // ??
    private Set<Status> statuses;
}

我尝试过以这种方式实现它,但解决方案会忽略状态表并尝试以 EnumType.ORDINAL 方式从 status_id 创建状态:

@ElementCollection(targetClass = Status.class)
@CollectionTable(name = "Document_Status", joinColumns = @JoinColumn(name = "document_id"))
@Column(name = "status_id", nullable = false)
private Set<Status> statuses;

@Enumerated(EnumType.STRING) 也无济于事。它开始在 Status 枚举中查找名称为“1”的值。

我可以像推荐的here 那样将枚举包装成实体。但是不创建包装实体就不能实现吗?

【问题讨论】:

  • 你的数据库结构修好了?
  • 不,不是。我只想将枚举值存储为字符串,以避免在枚举更改时出现问题。并且不想直接将字符串存储在 Document_Status 中以避免重复。如果您知道如何重构结构并满足要求,我将不胜感激。

标签: java hibernate jpa enums many-to-many


【解决方案1】:

我认为你应该将你的实体编辑成那样

状态

@Entity
public class Status {

    public enum StatusEnum {
        STORED, APPROVED
    }

    @Id
    @GeneratedValue
    private Integer id;

    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private StatusEnum status;
}

文档

@Entity
public class Document {

    @Id
    @GeneratedValue
    private long id;

    @ManyToMany
    private Set<Status> statuses;
}

【讨论】:

  • 感谢您的回答!但是如果不创建包装实体就不可能实现吗?难道我们没有一个“神奇”的注解来声明一个额外的连接吗?
  • @Raild 我不这么认为,你需要 ManyToMany 关系,所以你必须创建包装器
  • 你的解决方案不需要指定JoinTable吗?
  • @Raild 不,不是,如果你尝试了我的解决方案,它会很好地为你工作
  • 我有 java.sql.SQLException: ORA-00942: 表或视图不存在。但如果我添加它会起作用:@JoinTable(name = "Document_Status", joinColumns = @JoinColumn(name = "document_id"), inverseJoinColumns = @JoinColumn(name="status_id"))
【解决方案2】:

如果您要连接表并通过 id 识别枚举,则只需要一个包装器。你不需要这一切。

Document    Status            

╔════╗      ╔═════════════╦═════════════╗ 
║ id ║      ║ Document_id ║  statuses   ║ 
╠════╣      ╠═════════════╬═════════════╣ 
║  1 ║      ║  1          ║ STORED      ║   
║  2 ║      ║  2          ║ APPROVED    ║ 
║  3 ║      ║  2          ║ STORED      ║ 
║  4 ║      ║  3          ║ APPROVED    ║ 
║  5 ║      ╚═════════════╩═════════════╝ 
╚════╝                        


public enum Status {
    STORED, APPROVED
}

@Entity
public class Document {

    @Id
    @GeneratedValue
    private long id;


    @ElementCollection
    @Enumerated(EnumType.STRING)
    private Set<Status> statuses;
}

【讨论】:

  • 这里的问题是状态字符串值是重复的。如果我决定重命名其中一个,我将不得不更新所有相应的行。无论如何感谢您的帮助!
  • 恐怕是这样。我的问题的答案是,根据我的要求 + JPA,我必须处理包装器。
猜你喜欢
  • 2023-03-05
  • 2013-04-25
  • 2021-05-25
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 2012-11-25
相关资源
最近更新 更多