spring jpa 给外键赋值
最近在用spring data jap 的时候遇到一个问题,就是无法给一张表的外键赋予值,在A实体类中有一个属性的是另一个实体类B
如图
@JoinColumn的name指的是数据库表中的外键字段uid
这个外键在数据库中是vachar型的,但是在我的程序里却是一个实体类型的就是那个patient类
那么如果我们要在数据库表中添加一条数据,且还要为uid这个字段赋值的话,要怎么做呢?
如下图
这样就行了,这个问题困扰了我两三天,一开始也不是没想过用这种办法,而且实验了,但是失败了
失败的原因是因为@OneToOne注解被我设置了 cascade=CascadeType.PERSIST 这个属性,然后一运行就抛异常,不知道是什么原因 找了找网上的说法是 因为
"CascadeType.PERSIST只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)"这个,但我也不是很理解这句话的意思。之所以写这篇博客是因为在网上找不到把这个问题说的很清楚的博客或者资料,希望其他新人能脱离这个坑。
以下是实体类chat
@Entity(name = "chat")
public class chat {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
int id;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "msg", columnDefinition = "Text")
String msg;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "hfmsg", columnDefinition = "Text")
String hfmsg;
@Column(name = "savetime")
String savetime;
@OneToOne
@JoinColumn(name = "uid")
patient patient;
public int getId() {
return id;
}
public patient getPatient() {
return patient;
}
public void setPatient(patient patient) {
this.patient = patient;
}
public void setId(int id) {
this.id = id;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getHfmsg() {
return hfmsg;
}
public void setHfmsg(String hfmsg) {
this.hfmsg = hfmsg;
}
public String getSavetime() {
return savetime;
}
public void setSavetime(String savetime) {
this.savetime = savetime;
}
}
另一个实体类patient
@Entity(name="patient")
public class patient {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
int id;
@Column(name="uname")
String uname;
@Column(name="upass")
String upass;
@Column(name="tname")
String tname;
@Column(name="sex")
String sex;
@Column(name="age")
String age;
@Column(name="idcard")
String idcard;
@Column(name="tel")
String tel;
@Column(name="addr")
String addr;
@Column(name="delstatus")
String delstatus;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpass() {
return upass;
}
public void setUpass(String upass) {
this.upass = upass;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public String getDelstatus() {
return delstatus;
}
public void setDelstatus(String delstatus) {
this.delstatus = delstatus;
}
}
jpa外键关系映射(终极理解)
OneToOne
OneToOne是一对一关系,由一方的外键保存另一方的主键来维系双方的关系,而另一方需要获取关系映射而不需要维护外键即可获取对方,比如说Person和Address,由Person持有一个字段addr_id,保存Address的id,来维系双方的一对一关系
Person实体类如下:
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
@OneToOne
@JoinColumn(name = "addr_id", referencedColumnName = "id")
private Address address;
}
双向OneToOne
如果关系由一方维系,而另一方又想获取维系方的数据,比如说Person和Address,关系由Person的addr_id表字段来维系,而在Address实体类中又想获取Person,此时就只需要一个关系映射即可,而不需要Address再搞个外键来维系Person关系
Address实体类如下:
@Entity
@Table(name = "address")
public class Address {
@Id
@Column(name = "id")
private String id;
@Column
private String addrName;
@OneToOne(mappedBy = "address")
private Person person;
}
单向OneToMany
OneToMany是一对多的关系,而一般来说外键是存储在多的一方,所以使用单向的OneToMany显得有点怪异,因为此时指定的外键是对方的表字段,比如说Department和Person是一对多,一个部门有多个人员,而两者之间的关系是由Person中的dept_id表字段保存Department中的id主键来维系的,此时在部门类中使用单向OneToMany映射一对多关系时,放的实际是Person表中的dept_id字段
Department实体类如下:
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
@OneToMany
@JoinColumn(name = "dept_id", referencedColumnName = "id")
private List<Person> peopleList;
}
OneToMany和ManyToOne双向
单向的OneToMany是有点怪异的,因为外键不是存在One一方的表中,所以在一对多时,建议使用OneToMany和ManyToOne配合使用,由Many方使用外键维系关系,而One方只需要指定Many方关系映射的属性即可。
多方使用ManyToOne维系关系,如:Person实体类
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
@ManyToOne
@JoinColumn(name = "dept_id")
private Department department;
}
少方使用OneToMany,获取映射,如:Department实体类
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
@OneToMany(mappedBy = "department")
private List<Person> peopleList;
}
ManyToMany
多对多的关系中,往往需要借助第三张表,而这第三张表可以由JPA自动生成,此时就需要借助@JoinTable来自动生成第三张表,进行外键的管理,而@JoinTable由那一方指定都是可以的,另一方无需指定
Person实体类如下:
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
@ManyToMany
@JoinTable(
name = "pro_dept", // 自动生成的第三方表名,可省略
joinColumns = @JoinColumn(name = "per_id"), // 将本表id,存储到第三方表,列名为per_id
inverseJoinColumns = @JoinColumn(name = "dept_id") // 将对方表id,存储到第三方表,列名为dept_id
)
private List<Department> department;
}
Department实体类如下:
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
@ManyToMany(mappedBy = "department")
private List<Person> personList;
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。