文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用spring jpa 如何给外键赋值

2024-04-02 19:55

关注

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;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯