使用spring jpa 如何给外键赋值

目录
  • spring jpa 给外键赋值
  • jpa外键关系映射(终极理解)
    • OneToOne
    • 双向OneToOne
    • 单向OneToMany
    • OneToMany和ManyToOne双向
    • ManyToMany

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;
    /**
     * 由person表持有addr_id,保存address表的id
     * referencedColumnName是指addr_id指定的address的映射字段,默认是id主键
     */
    @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;
    /**
     *  一对一的被维系方,指定由Person实体类中的address属性进行关系映射管理
     *  从而获取Person数据
     */
    @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;
    /**
     * 单向一对多时,使用JoinColumn进行连接字段映射
     * 此时name为对方也就是Person表中的外键dept_id字段,
     * 而映射的referencedColumnName是本表的主键id字段
     */
    @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;
    /**
     * 多对一关系,由多方维系关系
     * 通过person表的dept_id字段和department表的id主键字段做关系映射
     */
    @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和ManyToOne配合使用时,由ManyToOne多方进行关系管理
     * 此时只需要指定管理映射属性,为Person中的department属性
     */
    @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;
    /**
     * 多对多,通过JoinTable生成第三方表,指定各自主键的存放列名
     * joinColumns:将本表id,存储到第三方表,列名为per_id
     * inverseJoinColumns:将对方表id,存储到第三方表,列名为dept_id
     * 注意:此处存放到第三方表的列名,需要和对方的外键名称相一致
     */
    @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;
    /**
     * 通过mappedBy表明由Person实体的department属性进行关系管理
     */
    @ManyToMany(mappedBy = "department")
    private List<Person> personList;
}

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

(0)

相关推荐

  • SpringDataJpa多表操作的实现

    目录 Jpa表关系分析步骤 关联关系的注解 @JoinColumn定义外键关联的字段名称 @OneToOne一对一关联关系 @OrderBy关联查询的时候的排序 @JoinTable关联关系表 @ManyToMany多对多 数据库中的表存在着多种关系,一对一,一对多,多对多 Jpa表关系分析步骤 开发过程中会有很多多表的操作,他们之间有着各种关系,在Jpa这种实现来了orm思想的框架中我们可以通过操作实体类来操作数据库,我们来连接下jap如何配置实体类来实现这种功能 确定表之间的关系 在数据库实

  • spring data jpa使用详解(推荐)

    使用Spring data JPA开发已经有一段时间了,这期间学习了一些东西,也遇到了一些问题,在这里和大家分享一下. 前言: Spring data简介: Spring Data是一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务. Spring Data 包含多个子项目: Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化 JPA - 简化创建 JPA 数据访问层和跨存储的持久层

  • 轻松搞定SpringBoot JPA使用配置过程详解

    SpringBoot整合JPA 使用数据库是开发基本应用的基础,借助于开发框架,我们已经不用编写原始的访问数据库的代码,也不用调用JDBC(Java Data Base Connectivity)或者连接池等诸如此类的被称作底层的代码,我们将从更高的层次上访问数据库,这在Springboot中更是如此,本章我们将详细介绍在Springboot中使用 Spring Data JPA 来实现对数据库的操作. JPA & Spring Data JPA JPA是Java Persistence API

  • Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

    1.简介 1.1 @EntityListeners 官方解释:可以使用生命周期注解指定实体中的方法,这些方法在指定的生命周期事件发生时执行相应的业务逻辑. 简单来说,就是监听实体对象的增删改查操作,并对实体对象进行相应的处理. 1.2 生命周期对应注解 JPA一共提供了7种注解,分别是: @PostLoad :实体对象查询之后 @PrePersist : 实体对象保存之前 @PostPersist :实体对象保存之后 @PreUpdate :实体对象修改之前 @PostUpdate :实体对象修

  • 使用spring jpa 如何给外键赋值

    目录 spring jpa 给外键赋值 jpa外键关系映射(终极理解) OneToOne 双向OneToOne 单向OneToMany OneToMany和ManyToOne双向 ManyToMany spring jpa 给外键赋值 最近在用spring data jap 的时候遇到一个问题,就是无法给一张表的外键赋予值,在A实体类中有一个属性的是另一个实体类B 如图 @JoinColumn的name指的是数据库表中的外键字段uid 这个外键在数据库中是vachar型的,但是在我的程序里却是一

  • 关于Django外键赋值问题详解

    本文主要给大家介绍关于Django外键赋值的相关内容,分享出来供大家参考学习,在开始之前,我们先来看一段代码: class Article(models.Model): title = models.CharField(max_length=1024, default='') ... def __str__(self): return 'Article pk:%d %s' % (self.pk, self.title[:30]) class ArticleContent(models.Model

  • jpa使用注解生成表时无外键问题及解决

    目录 jpa注解生成表时无外键 使用jpa自动建表不生成外键情况 情况1 情况2 jpa注解生成表时无外键 刚入手springboot时,在使用jpa实体注解生成表无外键.是因为jpa不知道使用何种Dialect创建,默认没有外键. 在配置文件加上 database-platform: org.hibernate.dialect.MySQL5InnoDBDialect 就好了. 使用jpa自动建表不生成外键情况 springboot项目搭配的jpa使用时候,有一对多的关系注解,那么自动会生成外键

  • 使用JPA单项一对多外键关联

    目录 JPA单项一对多外键关联 JPA外键关联保存踩坑 解决 JPA单项一对多外键关联 一对多即一个对象中包含又另外一个对象的集合. User主表代码 @Table(name="USER") @Entity public class User { private Integer id; private String username; private String userpassword; private String useraddress; private List<Ord

  • spring jpa设置多个主键遇到的小坑及解决

    目录 jpa设置多个主键遇到的坑 解决办法 jpa遇到多主键表如何进行查询 1.使用 List<Map<String, Object>>的方式去接收 2.自定义接收类 3.配置联合主键 jpa设置多个主键遇到的坑 由于项目需要,对多个业务表单独另外建立对应的历史版本记录表,为了原业务表数据能原封不动记录到历史版本表,需要建立组合主键,id+历史版本号作为主键唯一约束(rid+historyVersion). 在实体上需要设置为主键的字段加上注解,@Id,例如: /* * 主键-RI

  • DataSet 添加数据集、行、列、主键和外键等操作示例

    前台代码:html <%@ Page language="c#" Codebehind="CodeUse.aspx.cs" AutoEventWireup="false" Inherits="DsAndXML.CodeUse" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML>  

  • 关于在mongoose中填充外键的方法详解

    本文主要给大家介绍的是关于mongoose中填充外键的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: MongoDB MongoDB是典型的NoSQL数据库,因此不提供JOIN操作. 但有时我们仍然希望引用其他集合中的文档.此时便需要外键填充(population). mongoose是极具JavaScript特点的程序库,提供了极其简单和强大的填充功能. mongoose不仅支持填充单个文档,也支持多文档,甚至直接填充某个对象. 本文中部分代码来自mongoose文档

  • Spring JPA整合QueryDSL的示例代码

    前言 Spring JPA是目前比较常用的ORM解决方案,但是其对于某些场景并不是特别的方便,例如查询部分字段,联表查询,子查询等. 而接下来我会介绍与JPA形成互补,同时也是与JPA兼容得很好的框架QueryDSL. 同时由于目前主流使用Spring Boot,所以本文也会基于Spring Boot来进行演示 如果对于长文无感,但是又希望了解QueryDSL可以直接查看文章最后的总结 环境信息 以下为示例的关键环境信息 JDK 1.8 maven 3.6.1 SpringBoot 2.2.0.

  • spring jpa ManyToMany原理及用法详解

    1.java和jpa 中所有的关系都是单向的.这个关系数据库不同,关系数据库,通过外键定义并查询,使得反向查询总是存在的. 2.JPA还定义了一个OneToMany关系,它与ManyToMany关系类似,但反向关系(如果已定义)是ManyToOne关系. OneToMany与JPA中ManyToMany关系的主要区别在于,ManyToMany总是使用中间关系连接表来存储关系, OneToMany可以使用连接表或者目标对象的表引用中的外键源对象表的主键. @OneToMany(cascade =

  • python Django 反向访问器的外键冲突解决

    我有两个继承一个基类的Django模型: - Request - Inquiry - Analysis 请求有两个外键到内置用户模型. create_user = models.ForeignKey(User, related_name='requests_created') assign_user = models.ForeignKey(User, related_name='requests_assigned') 由于某种原因,我得到的错误 "Analysis.assign_user&quo

随机推荐