这是我的数据库,其中每个用户(选项卡。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 库
正如@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
元素。
尽管如此,您的代码仍然存在一些小问题:
user_id
实体中UserRole
列的重复映射。我认为甚至不可能使用重复的映射启动应用程序。insertable = false
的 @JoinColumn
属性中删除 UserRole.user
元素。使用这个注解,你将无法持久化 UserRole
对象。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 */
}