坑:这个来自新建实体类(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是多对多,是因为没有保存这些关联时的一些属性,如时间等。

因此,对于数据库表的设计,更多的是看所谓的实际需要,没有绝对的关联关系和表结构设计,只要是合理的,那么就应该给予支持。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐