我有这个ER图:
那被翻译成这些类:
User.java
@Entity
@Table(name = "user")
@NamedQueries({
@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")})
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;
@Column(name = "name")
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private Collection<UserHasNotify> userHasNotifyCollection;
UserHasNotify.java
@Entity
@Table(name = "user_has_notify")
@NamedQueries({
@NamedQuery(name = "UserHasNotify.findAll", query = "SELECT u FROM UserHasNotify u")})
public class UserHasNotify implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected UserHasNotifyPK userHasNotifyPK;
@Column(name = "has_read")
private String hasRead;
@JoinColumn(name = "notify_id", referencedColumnName = "id", insertable = false, updatable = false)
@ManyToOne(optional = false)
private Notify notify;
@JoinColumn(name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
@ManyToOne(optional = false)
private User user;
UserHasNotifyPK.java
@Embeddable
public class UserHasNotifyPK implements Serializable {
@Basic(optional = false)
@Column(name = "user_id")
private int userId;
@Basic(optional = false)
@Column(name = "notify_id")
private int notifyId;
通知.java
@Entity
@Table(name = "notify")
@NamedQueries({
@NamedQuery(name = "Notify.findAll", query = "SELECT n FROM Notify n")})
public class Notify implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "message")
private String message;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "notify")
private Collection<UserHasNotify> userHasNotifyCollection;
现在,我将添加一个实体User和Notify并在它们之间创建一个关系。
因此,我编写了以下代码段:
User user = new User();
user.setName("John");
Notify notify = new Notify();
notify.setMessage("Hello World");
userFacade.create(user);
notifyFacade.create(notify);
UserHasNotify uhn = new UserHasNotify();
uhn.setNotify(notify);
uhn.setUser(user);
uhn.setHasRead("ok");
uhnFacade.create(uhn);
但我收到此错误:
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'user_id' cannot be null
Error Code: 1048
Call: INSERT INTO user_has_notify (has_read, user_id, notify_id) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(com.test.entity.UserHasNotify[ userHasNotifyPK=null ])
为什么???????????
最佳答案
错误的原因可能在于远程通讯。您正在使用外观的事实意味着您正在与后端进行远程通信。
这意味着您在user
实例上设置的notify
和uhn
实例将被发送以保留在远程系统上,而本地实例则永远不会收到生成的ID。
要验证并解决此问题,可以扩展示例:
保存user
和notify
后,从后端获取它们。这应该返回具有现有ID的持久化实例。然后,您可以使用它们来存储您的uhn
关系。
编辑:我已经错过了UserHasNotify
是一个具有嵌入式ID的有状态关系的事实。在代码中,您永远不会设置此ID,因此提供程序会丢失它。
对于这种情况,我建议使用IdClass
而不是嵌入式ID-映射更易读,因此您可能不会两次映射User
和Notify
关系-一次在嵌入式PK中,一次再次在实体中;)
看起来像这样:
public class UserHasNotifyPK implements Serializable {
private Notify notify;
private User user;
...
}
。
@Entity
@Table(name = "user_has_notify")
@IdClass(UserHasNotifyPK.class)
@NamedQueries({
@NamedQuery(name = "UserHasNotify.findAll", query = "SELECT u FROM UserHasNotify u")})
public class UserHasNotify implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "has_read")
private String hasRead;
@Id
@JoinColumn(name = "notify_id", referencedColumnName = "id", insertable = false, updatable = false)
@ManyToOne(optional = false)
private Notify notify;
@Id
@JoinColumn(name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
@ManyToOne(optional = false)
private User user;
然后,您可以再次尝试相同的测试。