JPA Entites 上的空构造函数和设置器

发布于 2024-07-24 10:22:15 字数 140 浏览 4 评论 0原文

我不喜欢 JPA 实体上至少有一个空构造函数和公共设置器的要求。 虽然我理解 EntityManager 方面的问题,但这会使类不变量无效。

有人有解决方案吗(设计模式或习惯用法级别)?

谢谢!

伊戈尔

I don't like the requirement on have at least one empty constructor and public setters on JPA entities. While I understand the issue on the EntityManager side, this invalidates class invariants.

Does anyone have a solution for this (design pattern or idiom level) ?

Thanks!

Igor

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

惜醉颜 2024-07-31 10:22:15

对于 JPA,默认构造函数是必需的,但是,您不需要使用 setter。 您可以根据注释的放置位置选择属性访问策略(字段或方法)。

以下代码将使用直接字段访问,并且将作为没有 setter 的实体的一部分工作:

@Column(name = DESCRIPTION)
private String description;

public String getDescription() { return description; }

与使用 setter 的方法访问:

private String description;

@Column(name = DESCRIPTION)
public void setDescription(String description) {
     this.description = description;
}

public String getDescription() { return description; }

With JPA, the default constructor is required, however, you are not required to use setters. You can choose a property access strategy(field or method) based on where you place the annotations.

The following code will use direct field access and will work as a part of an entity without a setter:

@Column(name = DESCRIPTION)
private String description;

public String getDescription() { return description; }

Versus method access with a setter:

private String description;

@Column(name = DESCRIPTION)
public void setDescription(String description) {
     this.description = description;
}

public String getDescription() { return description; }
晚风撩人 2024-07-31 10:22:15

事实上,您应该同时拥有无参数构造函数和 getter 和 setter 方法。 这些要求在 规格

无参数构造函数要求可以在我的副本的第 17 页找到:

实体类必须有无参数
构造函数。 实体类可能有
其他构造函数也是如此。 无arg
构造函数必须是公共的或
受保护。

第 18 页对访问器方法有要求:

实体的持久状态是
由实例变量表示,
这可能对应于JavaBeans
特性。 实例变量可以
只能从内部直接访问
实体的方法
实体实例本身。 实例
变量不得被访问
该实体的客户。 的状态
该实体可供客户使用
仅通过实体的访问器
方法(getter/setter 方法)或
其他商业方式。 实例
变量必须是私有的、受保护的、
或包可见性。

字段与属性访问指示 JPA 提供程序如何与您的实体交互,而不是客户端应用程序如何与其交互。 客户端应始终使用 get 和 set 方法。

一些 JPA 提供商在这些要求方面更为宽松,您可以将构造函数设为私有(如上所述)给特定供应商。 不过,该应用程序可能不可移植,因此如果您将来迁移,您可能会感到惊讶。

所以我不建议完全省略这些方法。 为了解决这个问题,我将 public no-arg ctor 标记为已弃用(在 javadoc 中放入有关它仅供 JPA 提供程序使用的内容)。 set 方法可以包含您想要维护不变量的逻辑。

它并不理想,但它应该可以防止意外使用错误的构造函数(我假设您有一个设置不变量的构造函数)。

In point of fact you should have both a no-args constructor and getter and setter methods. The requirements are indicated in section 2.1 of the spec.

The no-arg constructor requirement is found on page 17 in my copy :

The entity class must have a no-arg
constructor. The entity class may have
other constructors as well. The no-arg
constructor must be public or
protected.

Page 18 has the requirement for accessor methods :

The persistent state of an entity is
represented by instance variables,
which may correspond to Java- Beans
properties. An instance variable may
be directly accessed only from within
the methods of the entity by the
entity instance itself. Instance
variables must not be accessed by
clients of the entity. The state of
the entity is available to clients
only through the entity’s accessor
methods (getter/setter methods) or
other business methods. Instance
variables must be private, protected,
or package visibility.

Field vs. Property access indicates how the JPA provider interacts with your entity, not how the client application interacts with it. The client should always use get and set methods.

Some JPA providers are more lenient in these requirements and you may be able to make the constructor private (as suggested above) with a specific vendor. The application might not be portable though so you could be in for a surprise if you migrate in the future.

So I wouldn't recommend omitting the methods entirely. In order to resolve the problem I'd mark the public no-arg ctor as deprecated (put something in the javadoc about it being for JPA provider use only). The set methods can contain the logic you want to maintain your invariants.

It isn't ideal but it should prevent the wrong ctor from being used by accident (I'm assuming you have a ctor that sets the invariants).

傾旎 2024-07-31 10:22:15

OpenJPA 可以添加无参数构造函数作为增强实体的一部分。

我们很清楚,JPA 规范中强制要求了该要求。 前面的答案说您可以将无参数构造函数设为私有,但这不符合规范(我看到链接指向 Hibernate 特定页面)。 该规范规定实体必须具有公共或受保护的无参数对象。

-瑞克

OpenJPA can add a no-arg ctor as a part of enhancing your entities.

Just so we're clear, the requirement is mandated in the JPA spec. The previous answer says that you can make the no-arg ctor private, but that is not compliant with the spec(I see the link points to a Hibernate specific page). The spec states that an Entity must have a public or protected no-arg ctor.

-Rick

野却迷人 2024-07-31 10:22:15

使用 DataNucleus,如果您不想,则不必添加默认构造函数; 它将通过字节码增强自动添加。 您还可以保留字段而不是属性,因此不需要公共设置器。

--Andy (DataNucleus)

With DataNucleus you don't have to add a default constructor if you don't want to; it will be added automatically by bytecode enhancement. Also you could persist fields instead of properties, hence no need for public setters.

--Andy (DataNucleus)

若水微香 2024-07-31 10:22:15

只需将您的构造函数设置为受保护或私有,这样您就可以保留类不变量!

public class Person {
 private String firstName;
 private String lastName;

 public Person(String firstName, String lastName) {
  setFirstName(firstName);
  setLastName(lastName);
 }

 // private no-arg constructor for hibernate.
 private Person() {

 }

 public String getFirstName() {
  return firstName;
 }
 public String getLastName() {
  return lastName;
 }

 // private setters for hibernate
 private void setFirstName(String nme) {
  firstName = nme;
 }
 private void setLastName(String nme) {
  lastName = nme;
 }
}

请参阅http://www.javalobby.org/java/forums/m91937279.html

Just make your constructor protected or private, so you preserve the class invariants!

public class Person {
 private String firstName;
 private String lastName;

 public Person(String firstName, String lastName) {
  setFirstName(firstName);
  setLastName(lastName);
 }

 // private no-arg constructor for hibernate.
 private Person() {

 }

 public String getFirstName() {
  return firstName;
 }
 public String getLastName() {
  return lastName;
 }

 // private setters for hibernate
 private void setFirstName(String nme) {
  firstName = nme;
 }
 private void setLastName(String nme) {
  lastName = nme;
 }
}

see http://www.javalobby.org/java/forums/m91937279.html for details.

儭儭莪哋寶赑 2024-07-31 10:22:15

是的,保留字段而不是属性,但是如果您不需要默认构造函数,通常(除非字节码增强器做了一些技巧)您将无法摆脱它。

您必须允许 jpa 实现实例化该类,因此公共默认构造函数是必需的。

Yes, persist fields instead of properties, but on the not wanting a default constructor you're typically (unless the byte code enhancer does some trick) you're not going to get away from it.

You have to allow your jpa implementation to instantiate the class, so a public default constructor is mandatory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文