使用@OneToOne 关系保存实体时出错(未标记级联 PERSIST 的关系)

问题描述 投票:0回答:1

这是我的数据库,其中每个用户(选项卡。users)都有其角色(选项卡。userroles),具有一对一的关系。外键是选项卡用户角色中的“user id”。

当我尝试保留实体用户 (eclipselink) 时,我收到错误消息:

Error saving entity User{id=0, [email protected], [email protected], password=mypassword, userRole=UserRole(id=null, role=admin, userId=0)}
jakarta.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: UserRole(id=null, role=admin, userId=0).

实体用户

@Entity
@Table(name = "users")
@Data
@XmlRootElement
public class User implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @Basic(optional = false)
  @NotNull
  @Size(min = 1, max = 45)
  @Column(name = "username")
  private String username;
  // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
  @Basic(optional = false)
  @NotNull
  @Size(min = 1, max = 128)
  @Column(name = "email")
  private String email;
  @Basic(optional = false)
  @NotNull
  @Size(min = 1, max = 128)
  @Column(name = "password")
  private String password;
  

  @OneToOne(mappedBy = "user", optional = false, fetch = FetchType.EAGER)
  private UserRole userRole;

实体用户角色

@Entity
@Table(name = "userroles")
@Data
@ToString(doNotUseGetters = true)
public class UserRole implements Serializable {

  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @Size(max = 45)
  @Column(name = "role")
  private String role;
  @Basic(optional = false)
  @NotNull
  @Column(name = "user_id")
  private int userId;


  @OneToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL)
  @JoinColumn(name = "user_id", insertable=false, updatable=false)
  @ToString.Exclude
  private User user;

保存方法:

...
save(aUser);
..

public void save(Object entity) throws Exception {
    EntityManager em = getFactory().createEntityManager();
    try {
      EntityTransaction t = em.getTransaction();
      try {
        t.begin();
        em.persist(entity);
        t.commit();
      } catch (Exception e) {
        throw new Exception("Error saving entity " + entity, e);
      } finally {
        if (t.isActive()) {
          t.rollback();
        }
      }
    } finally {
      em.close();
    }
  }

我认为映射是正确的,但是出现错误.. 我也用 lombok 库

jpa entity eclipselink
1个回答
0
投票

正如@chris 在他的评论中指出的那样,您正在调用

User
EntityManager#persist
对象具有对
UserRole
的初始化引用。

这个可以在你提交的日志中看到:

Error saving entity User {
  id=0, 
  [email protected], 
  [email protected], 
  password=mypassword, 
  userRole=UserRole(id=null, role=admin, userId=0) <= here!
}

您可以解决此错误:1) 保留引用

null
或 2) 在注释中包含
cascade = CascadeType.PERSIST
元素。

尽管如此,您的代码仍然存在一些小问题:

  1. 删除
    user_id
    实体中
    UserRole
    列的重复映射。我认为甚至不可能使用重复的映射启动应用程序。
  2. insertable = false
    @JoinColumn
    属性中删除
    UserRole.user
    元素。使用这个注解,你将无法持久化
    UserRole
    对象。
  3. cascade = CascadeType.ALL
    实体中使用
    UserRole
    要小心。如果您首先确定需要级联操作的位置,而不是在您的注释上使用
    CascadeType.ALL
    会怎么样?有点像我们之前做过的。

他们看起来或多或少是这样的:

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Basic(optional = false)
    private String username;
    @Basic(optional = false)
    private String email;
    @Basic(optional = false)
    private String password;
    @OneToOne(mappedBy = "user", optional = false, orphanRemoval = true, cascade = CascadeType.PERSIST)
    private UserRole userRole;

    /* constructors, getters and some setters */
}

@Entity
@Table(name = "userroles")
public class UserRole {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Basic(optional = false)
    private String role;
    /* private int userId; <== remove this */
    @OneToOne(optional = false)
    @JoinColumn(name = "user_id", updatable = false)
    private User user;

    /* constructors, getters and some setters */
}
© www.soinside.com 2019 - 2024. All rights reserved.