5

我正在使用 Hibernate 5 和 Spring 3.2.4。我正在设计一个用户实体,我想在其中包含对创建实体的用户的引用 - 所以是一个自我引用。自引用本身并没有太大问题,但我想将该字段指定为非空。这可能吗?如果字段不为空,因为引用的实体尚不存在,如何在数据库中创建第一个条目?

前任:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long User.id;

    @NotNull
    private String username;

    private String password;

    @NotNull
    private User user;


    // getters and setters omitted for brevity
}

如果我尝试:

User u = new User();
u.setUsername("username");
u.setCreatedBy(u);

并尝试坚持u,我收到以下错误消息:

Caused by: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation: com.domain.User.createdBy -> com.domain.User

我知道 Hibernate 抱怨它不能引用瞬态实例(即:) ,但除非我有一个可以引用的非空用户,否则我u不能坚持下去。u但是在一个空的数据库中,没有这样的条目。

这种配置是不可能的吗?或者有没有办法解决这个问题?

4

3 回答 3

4

我不理解这个 Roo 注释,我不使用特定于 Hibernate 的注释,只使用 JPA。我对自我引用没有任何问题。但我有一些提示给你:

  1. 如前所述,使用@ManyToOne注释。
  2. AFAIK,@NotNull注释(或nullable中的字段@Column)不影响映射,仅影响 DDL 生成。我不使用域模型中的 DDL 生成,我从不指定这个。相反,我使用optional.@ManyToOne
  3. 您使用什么标识符生成策略?如果自增,自引用是不可能有NOT NULL约束的。所以要么使用基于序列的标识符生成器,​​要么删除约束。我会先用。
  4. 正如我所提到的,当您有约束时,将optional字段设置为@ManyToOneto 。否则,Hibernate 会尝试进行两个查询:使用set to插入然后更新。第一个查询在启用约束的情况下失败。falseNOT NULLcreatedBy_idNULLcreatedBy_idNOT NULL
于 2013-11-29T06:05:01.153 回答
2

我找到了解决方案。您必须为您的 ID 使用序列生成器(而不是默认的自动生成的 ID)。然后它工作。

@Entity
public class UserModel {
  /**
   * We must use a sequence for generating IDs,
   * because of the self reference .
   * https://vladmihalcea.com/2014/07/15/from-jpa-to-hibernates-legacy-and-enhanced-identifier-generators/
   */
  @Id
  @GeneratedValue(generator = "sequence", strategy=GenerationType.SEQUENCE)
  @SequenceGenerator(name = "sequence", allocationSize = 10)
  private Long id;

  /** reference to a parent user, e.g. the manager */
  @ManyToOne(optional = false)
  @NotNull
  UserModel parentUser;

  [...]

原因如下:当 Hibernate 尝试插入新用户时,它还尝试验证对 parentUser 的引用。但这对于我们要插入的第一个用户来说会失败,或者当用户引用自己时也会失败。

但是,当使用序列生成 ID 时,新/下一个 ID 在插入时已经知道。

于 2017-01-04T20:20:10.783 回答
0

由于注解,字段createdByofu不能为空@NOTNULL。但是u引用自身并且在保存之前它不会持久化。您可以为 设置另一个持久化Useru而不是自身。

于 2013-11-29T04:19:10.847 回答