【问题标题】:JPA: is the default constructor required to be empty?JPA:默认构造函数是否必须为空?
【发布时间】:2012-11-26 19:51:18
【问题描述】:

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

谢谢。

【问题讨论】:

标签: java jpa constructor eclipselink


【解决方案1】:

通过 JPA 最小化运行时开销,但在用户代码中创建新实例时强制执行约束:

  • 使用 protected 无参数构造函数,没有/很少代码,以促进最快路径实现,并且
  • 客户端代码的 n-arg 构造函数,包含根据约束实例化新对象所需的代码。

【讨论】:

    【解决方案2】:

    简短的回答是否定的。不需要为空。

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

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

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

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

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

    【讨论】:

    • 以及,通过扩展,实现实例的额外(浪费)时间。
    • @RichardSitze - 这是一个考虑因素。但一般来说,与物化对象所花费的时间相比,不必要的初始化所花费的时间是微不足道的。
    • "简短的回答是否定的。它不需要为空。"但Java Persistence 2.1 specification 明确指出:“实体类必须有一个无参数构造函数。实体类也可能有其他构造函数。无参数构造函数必须是公共的或受保护的。”
    • 这些都不是说无参数构造函数必须有一个空的主体。这就是本次问答的内容。
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 2012-03-04
      相关资源
      最近更新 更多