【问题标题】:String as Entity ID inserted by user [EclipseLink]字符串作为用户插入的实体 ID [EclipseLink]
【发布时间】:2017-10-28 05:18:45
【问题描述】:

[简介]

  1. 数据库:Apache Derby
  2. JPA:EclipseLink

嘿,我正在寻找答案,但找不到任何答案,所以就这样吧。我正在编写简单的数独应用程序,我想添加的下一个功能是将我的数独板保存在数据库中,并在需要时检索它们。这是我的主要两个类的 UML 图: SudokuBoard.uml 我的两个实体的结构如下:

数独板实体:

@Entity
public class SudokuBoard implements Serializable, Cloneable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private static final long serialVersionUID = 1L;

@OneToMany(cascade=CascadeType.PERSIST)
private ArrayList<SudokuField> board;

public ArrayList<SudokuField> board() {
    return board;
}

public void setBoard(ArrayList<SudokuField> board) {
    this.board= board;
}

public Long etId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
} 

SudokuField 实体:

@Entity
public class SudokuField implements Serializable, Comparable<SudokuField>, 
Cloneable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Transient
private static final Logger logger = 
LoggerFactory.getLogger(SudokuField.class);
@Transient
private static final long serialVersionUID = 1L;

@Basic(fetch = FetchType.EAGER)
@Column(name = "Value")
private int value;

@ManyToOne
@JoinColumn(name = "board_fk", referencedColumnName = "id")
private SudokuBoard sudokuBoard;

DAO 中的执行:

@Override
public void write(SudokuBoard obj, String path) throws 
FileNotFoundException, IOException {
    entityManager.getTransaction().begin();
    entityManager.persist(obj);
    entityManager.getTransaction().commit();
}

[问题]

  1. 我想知道是否有可能不使用自动生成的密钥,而是在 SudokuBoard 实体中使用字符串作为 PK。在我的应用程序中,我实现了绑定,因此我想保存 SudokuBoard 的同一个对象,该对象随着时间的推移以不同的名称发生变化。

希望我清楚地表达了我的意图。感谢您提供任何帮助和提示。

【问题讨论】:

    标签: java jpa eclipselink derby


    【解决方案1】:

    使用String 作为主键很简单——只需声明它并删除@GeneratedValue 注释。

    但是,更改主键(如果这就是您所说的“以不同的名称保存相同的对象 (...)”的意思)是不可能的。如果您尝试在不同的主键下 persist/merge 现有实体,JPA 将引发异常或将其视为新实体,从而导致数据库中的重复条目。简而言之,将 id 分配给实体是永久性的。

    总而言之,我建议您保留一个自动生成的代理键并声明另一个唯一的 String 字段作为名称。使用技术领域传达业务信息很少是一个好主意。

    【讨论】:

    • 通过“以不同的名称保存同一个对象 (...)”,我的意思是我希望拥有同一个对象的多个条目,这些条目的状态随着时间的推移而不同。现在,当我实例化对象时,我不能多次持久化它,因为它的 PK 只分配一次,并且每当我尝试执行此操作时都会引发重复键异常。我想实现的概念是:1)创建随机数独字段2)将其保存到数据库3)填充同一板的一些缺失字段4)能够以不同的ID再次保存它
    • 好的,现在我明白了。不幸的是,除了手动创建和保存SudokuBoard SudokuFields 的副本之外,我认为没有简单的方法可以实现您想要的。你不觉得你的数据模型有点过于复杂吗? SudokuFields 真的需要自己的持久身份吗?我建议使用整数列表。如果您绝对需要单独的 SudokuField 模型,我仍然会将 @OneToMany 映射替换为 @ElementCollection@Embeddables。
    • 这样,您将能够detachSudokuboard,更新主键,并将persist作为一个新实体,而不是手动复制整个结构。不再需要为SudokuFields 列表提供新副本。
    • 这样做,我将能够在数据库中存储多个板或只是最实际的一个?将尝试实施。感谢您的支持和简要说明
    • 通常情况下,您 merge 是一个分离的实体,同时保留原始 id 以“显示”实体管理器您现在期望它具有什么状态。但是,当您更改 id 然后 persist 一个分离的实体时,它将被视为全新的。此操作不会以任何方式影响原始实体,因此您最终会得到两个实体而不是一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多