9

使用 JPA 时默认构造函数是否必须为空?由于我不知道 JPA 内部是如何工作的,我以某种方式担心当默认构造函数自己执行某些操作(例如用默认值填充属性等)时,JPA 可能会错误地初始化对象。

谢谢。

4

3 回答 3

10

为了最大限度地减少 JPA 的运行时开销,但在用户代码中创建新实例时强制执行约束:

  • 使用没有/很少代码的受保护的无参数构造函数来促进最快路径实现,以及
  • 客户端代码的 n-arg 构造函数,包含根据约束实例化新对象所需的代码。
于 2012-12-09T00:38:28.953 回答
7

最简洁的答案是不。它不需要为空。

但是,您需要注意,当 JPA 实现从持久化实例化实例时,它将在无参数构造函数完成后对实例执行操作。这可能会撤消您的构造函数所做的事情。

要了解构造函数是否需要为空,您需要考虑构造函数将在两种情况下被调用。

  • 当您创建“新”对象时,构造函数需要生成一个已充分初始化以供普通代码使用的对象。应该处理需要初始化为非默认状态的字段。

  • 当 JPA 从持久存储中具体化一个对象时,具体化将“填充”新构造实例的细节。这通常会覆盖构造对象的对象状态。

当然,您的代码可能被设计为不直接使用无参数构造函数。这使得第一个场景没有实际意义,也使得可能发生的潜在浪费的“双重初始化”变得毫无意义。

于 2012-12-09T00:24:29.350 回答
5

更长的答案是:它不应该是空的,大多数时候。例如,想象以下实体:

@Entity
public class Team {
    @Id
    private Long id;

    @OneToMany
    private Set<Player> players;

    // getters
}

当 JPA 加载实例时,播放器集永远不会为空。它可以为空,但不能为空。但是当你创建一个新的 Team,或者当你在单元测试中使用 Team 实例时,这个不变量也应该得到保证。所以这个类应该写成

@Entity
public class Team {
    @Id
    private Long id;

    @OneToMany
    private Set<Player> players = new HashSet<Player>(0);

    // getters
}

这相当于

@Entity
public class Team {
    @Id
    private Long id;

    @OneToMany
    private Set<Player> players;

    public Team() {
        this.players = new HashSet<Player>(0);
    }
    // getters
}
于 2012-12-09T00:31:24.720 回答