坑:这个来自新建实体类(New-..JPA entities from tables)
大概会造成三种错误:一种是①标题这种,一种大意是②至少要有一个非只读的列(大意关键词non-read only,There should be one non-read-only mapping defined for the primary key field),还有一个大意是③update错误之类的。
全是因为这个错误。
当你这样生成entity时,需要注意以下问题:
当存在多对多关联时,即必须用一个表保存对应的关联关系(老师有多个学生,学生有多个老师),这时候,这个表务必这样取名:ref_teacher_student,这样把这个表选中也不会生成真正的实体,而是建立join_table这样的关联关系。
同时标题和上面列出来的错误是因为如下原因:
如:选课表里面,主键是学生ID+课程ID,这时,JPA自动为你创建StudentClassPK的主键类,里面的sid和cid是含有这个的(insertable=false, updatable=false),而在选课表对应的实体中,除了主键和相关属性外,还有Student和Class的对象,这时JoinColumn里面是没有(insertable=false, updatable=false)的。
这样直接运行,会造成标题中的错误;
如果将JoinColumn里面加上insertable=false, updatable=false,那么会产生第二个错误
解决上述问题的方法是把PK中的insertable=false, updatable=false改到选课表对应实体中,Student和Class对象后面的JoinColumn里面。
解决后代码如下(此处代码是User、Test的例子) admin表没有和其他表产生关联关系,所以没有参与上面的描述中
自动生成后的联系:
自动生成后的实体类:
以UserTest为例,说明关于insertable=false的修改
package entity;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the user_test database table.
*
*/
@Entity
@Table(name="user_test")
@NamedQuery(name="UserTest.findAll", query="SELECT u FROM UserTest u")
public class UserTest implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private UserTestPK id;
private int issubmit;
private int score;
//bi-directional many-to-one association to Test
@ManyToOne
@JoinColumn(name="tid",insertable=false, updatable=false)
private Test test;
//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="uid",insertable=false, updatable=false)
//这里的insertable=false等原来在PK类里面的uid和tid里面
private User user;
public UserTest() {
}
public UserTestPK getId() {
return this.id;
}
public void setId(UserTestPK id) {
this.id = id;
}
public int getIssubmit() {
return this.issubmit;
}
public void setIssubmit(int issubmit) {
this.issubmit = issubmit;
}
public int getScore() {
return this.score;
}
public void setScore(int score) {
this.score = score;
}
public Test getTest() {
return this.test;
}
public void setTest(Test test) {
this.test = test;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
}
package entity;
import java.io.Serializable;
import javax.persistence.*;
/**
* The primary key class for the user_test database table.
*
*/
@Embeddable
public class UserTestPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column()
private int tid;
@Column()
//这里自动生成的时候有insertable=false等
private String uid;
public UserTestPK() {
}
public int getTid() {
return this.tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getUid() {
return this.uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof UserTestPK)) {
return false;
}
UserTestPK castOther = (UserTestPK)other;
return
(this.tid == castOther.tid)
&& this.uid.equals(castOther.uid);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.tid;
hash = hash * prime + this.uid.hashCode();
return hash;
}
}
注意:本质上User和Test、User和Submit(对应TEST的SUBMIT)都是多对多关系,为啥拆成两个一对多,在中间加上了UserTest和UserSubmit是因为需要保存一些值,如时间、分数等,Test和Question是多对多,是因为没有保存这些关联时的一些属性,如时间等。
因此,对于数据库表的设计,更多的是看所谓的实际需要,没有绝对的关联关系和表结构设计,只要是合理的,那么就应该给予支持。