【Spring Boot】关系映射开发(一):一对一映射

关系映射开发(一):一对一映射

  • 1.认识实体间关系映射
    • 1.1 映射方向
    • 1.2 ORM 映射类型
  • 2.实现 “一对一” 映射
    • 2.1 编写实体
      • 2.1.1 新建 Student 实体
      • 2.1.2 新建 Card 实体
    • 2.2 编写 Repository 层
      • 2.2.1 编写 Student 实体的 Repository
      • 2.2.2 编写 Card 实体的 Repository
    • 2.3 编写 Service 层
      • 2.3.1 编写 Student 的 Service 层
      • 2.3.2 编写 Card 的 Service 层
    • 2.4 编写 Service 实现
      • 2.4.1 编写 Student 实体的 Service 实现
      • 2.4.2 编写 Card 实体的 Service 实现
    • 2.5 编写测试
  • 3.单向 / 双向 OneToOne
    • 3.1 单向一对一关系的拥有端
    • 3.2 单向一对一关系的接收端
    • 3.3 双向一对一关系的接收端

1.认识实体间关系映射

对象关系映射object relational mapping)是指通过将对象状态映射到数据库列,来开发和维护对象和关系数据库之间的关系。它能够轻松处理(执行)各种数据库操作,如插入、更新、 删除等。

1.1 映射方向

ORM 的映射方向是表与表的关联(join),可分为两种。

  • 单向关系:代表一个实体可以将属性引用到另一个实体。即只能从 A 表向 B 表进行联表查询。
  • 双向关系:代表每个实体都有一个关系字段(属性)引用了其他实体。

1.2 ORM 映射类型

  • 一对一@OneToOne):实体的每个实例与另一个实体的单个实例相关联。
  • 一对多@OneToMany):一个实体的实例可以与另一个实体的多个实例相关联。
  • 多对一@ManyToOne): —个实体的多个实例可以与另一个实体的单个实例相关联。
  • 多对多@ManyToMany):—个实体的多个实例可能与另一个实体的多个实例有关。在这个映射中,任何一方都可以成为所有者方。

2.实现 “一对一” 映射

一对一 映射首先要确定实体间的关系,并考虑表结构,还要考虑实体关系的方向性。

若为 双向关联,则在保存实体关系的实体中要配合注解 @JoinColumn;在没有保存实体关系的实体中,要用 mappedBy 属性明确所关联的实体。

下面通过实例来介绍如何构建一对一的关系映射。

2.1 编写实体

2.1.1 新建 Student 实体

package com.example.demo.entity;

import lombok.Data;
import javax.persistence.*;

@Entity
@Data
@Table(name = "stdu")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    @Column(columnDefinition = "enum('male','female')")
    private String sex;
    /**
     * Description:
     * 建立集合,指定关系是一对一,并且申明它在cart类中的名称
     * 关联的表为card表,其主键是id
     * 指定外键名为card_id
     */
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "card_id")
    private Card card;
}

在这里插入图片描述

2.1.2 新建 Card 实体

package com.example.demo.entity;

import lombok.Data;
import javax.persistence.*;

@Entity
@Table(name = "card")
@Data
public class Card {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private Integer num;
}

在这里插入图片描述

2.2 编写 Repository 层

2.2.1 编写 Student 实体的 Repository

package com.example.demo.repository;

import com.example.demo.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import javax.transaction.Transactional;

public interface StudentRepository extends JpaRepository<Student, Long> {
    Student findById(long id);
    Student deleteById(long id);
}

2.2.2 编写 Card 实体的 Repository

package com.example.demo.repository;

import com.example.demo.entity.Card;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface CardRepository extends JpaRepository<Card, Long>, JpaSpecificationExecutor<Card> {
    Card findById(long id);
}

2.3 编写 Service 层

2.3.1 编写 Student 的 Service 层

package com.example.demo.service;

import com.example.demo.entity.Student;
import java.util.List;

public interface StudentService {
    public List<Student> getStudentlist();
    public Student findStudentById(long id);
}

2.3.2 编写 Card 的 Service 层

package com.example.demo.service;

import com.example.demo.entity.Card;
import java.util.List;

public interface CardService {
    public List<Card> getCardList();
    public Card findCardById(long id);
}

2.4 编写 Service 实现

2.4.1 编写 Student 实体的 Service 实现

package com.example.demo.service.impl;

import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentRepository studentRepository;

    @Override
    public List<Student> getStudentlist() {
        return studentRepository.findAll();
    }

    @Override
    public Student findStudentById(long id) {
        return studentRepository.findById(id);
    }
}

2.4.2 编写 Card 实体的 Service 实现

package com.example.demo.service.impl;

import com.example.demo.entity.Card;
import com.example.demo.repository.CardRepository;
import com.example.demo.service.CardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class CardServiceImpl implements CardService {
    @Autowired
    private CardRepository cardRepository;

    @Override
    public List<Card> getCardList() {
        return cardRepository.findAll();
    }

    @Override
    public Card findCardById(long id) {
        return cardRepository.findById(id);
    }
}

2.5 编写测试

完成了上面的工作后,就可以测试它们的关联关系了。

package com.example.demo.entity;

import com.example.demo.repository.CardRepository;
import com.example.demo.repository.StudentRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.junit.Assert.*;

@SpringBootTest
@RunWith(SpringRunner.class)
public class oneToOneTest {
    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private CardRepository cardRepository;

    @Test
    public void testOneToOne() {
        Student student1 = new Student();
        student1.setName("赵大伟");
        student1.setSex("male");
        Student student2 = new Student();
        student2.setName("赵大宝");
        student2.setSex("male");

        Card card1 = new Card();
        card1.setNum(422802);
        student1.setCard(card1);
        studentRepository.save(student1);
        studentRepository.save(student2);
        Card card2 = new Card();
        card2.setNum(422803);
        cardRepository.save(card2);
        /**
         * Description: 获取添加之后的id
         */
        Long id = student1.getId();
        /**
         * Description: 删除刚刚添加的student1
         */
        studentRepository.deleteById(id);
    }
}

首先,注释掉 studentRepository.deleteById(id);,看一下数据库。因为级联的原因,在运行 studentRepository.save(student1); 时,就保存了 card1,所以不需要像 cardRepository.save(card2); 一样运行 cardRepository.save(card1);

在这里插入图片描述
在这里插入图片描述
运行代码,在控制台输出如下测试结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以看到,同时在两个表 stducard 中添加了内容,然后删除了刚添加的有关联的 stducard 表中的值。如果没有关联,则不删除。

🚀 在双向关系中,有一方为关系的 发出端,另一方是关系的 反端,即 Inverse 端(接收端)。对于双向的一对一关系映射,发出端和接收端都要使用注解 @OneToOne,同时定义一个接收端类型的字段属性和 @OneToOne 注解中的 mappedBy 属性。这个在双向关系的接收端是必需的。

3.单向 / 双向 OneToOne

单向一对一 是关联关系映射中最简单的一种,简单地说就是可以从关联的一方去查询另一方,却不能反向查询。我们用下面的例子来举例说明,清单 1 中的 Person 实体类和清单 2 中的 Address 类就是这种单向的一对一关系,我们可以查询一个 Person 的对应的 Address 的内容,但是我们却不能由一个 Address 的值去查询这个值对应的 Person。

3.1 单向一对一关系的拥有端

@Entity 
public class Person implements Serializable { 
	private static final long serialVersionUID = 1L; 
	@Id 
	@GeneratedValue(strategy = GenerationType.AUTO) 
	private Long id; 
	private String name; 
	private int age; 
	@OneToOne 
	private Address address; 
 
	// Getters & Setters 
}

3.2 单向一对一关系的接收端

@Entity 
public class Address implements Serializable { 
	private static final long serialVersionUID = 1L; 
	@Id 
	@GeneratedValue(strategy = GenerationType.AUTO) 
	private Long id; 
	private String street; 
	private String city; 
	private String country;
	
	// Gettes & Setters 
}

在这里插入图片描述
从上面的 ER 图可以看出,这种单向的一对一关系在数据库中是以外键的形式被映射的。其中关系的 发出端 存储一个指向关系的接收端的一个外键。在这个例子中 person 表中的 ADDRESS_ID 就是指向 address 表的一个外键,缺省情况下这个外键的字段名称,是以它指向的表的名称加下划线 _ID 组成的。当然我们也可以根据我们的喜好来修改这个字段,修改的办法就是使用 @JoinColumn 这个注解。在这个例子中我们可以将这个注解注释在 Person 类中的 Address 属性上去。

3.3 双向一对一关系的接收端

@Entity 
public class Address implements Serializable { 
	private static final long serialVersionUID = 1L; 
	@Id 
	@GeneratedValue(strategy = GenerationType.AUTO) 
	private Long id; 
	private String street; 
	private String city; 
	private String country; 
	@OneToOne(mappedBy = "address") 
	private Person person; 
	
	// Gettes & Setters 
}

双向关系有一方为关系的拥有端,另一方是关系的接收端(反端),也就是 Inverse 端。在这个例子中 Person 拥有这个关系,而 Address 就是关系的 Inverse 端。Address 中我们定义了一个 person 属性,在这个属性上我们使用了 @OneToOne 注解并且定义了它的 mappedBy 属性,这个在双向关系的 Inverse 端是必需的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/769268.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AMEYA360代理:海凌科60G客流量统计雷达模块 4T4R出入口绊数计数

数字化时代&#xff0c;不管是大型商城还是各种连锁店&#xff0c;客流统计分析都可以帮助企业更加精准地了解顾客需求和消费行为。 海凌科推出一款专用于客流量统计的60G雷达模块&#xff0c;4T4R&#xff0c;可以实时进行固定范围内的人体运动轨迹检测&#xff0c;根据人体的…

0703_ARM7

练习&#xff1a; 封装exti&#xff0c;cic初始化函数 //EXTI初始化 void hal_key_exti_init(int id,int exticr,int mode){//获取偏移地址int address_offset (id%4)*8;//获取寄存器编号int re_ser (id/4)1;//printf("address_offset%d,re_ser%d\n",address_o…

学会python——用python编写一个电子时钟(python实例十七)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.电子时钟程序 3.1 代码构思 3.2代码实例 3.3运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性…

软件模型分类及特点

在软件开发的世界里&#xff0c;我们经常会遇到业务模型、系统模型和软件模型这三个层次。这些模型各有特点&#xff0c;相互之间也有着紧密的联系。通过理解这三个层次之间的映射关系&#xff0c;我们能更好地理解和掌握软件开发的全过程 1. 业务模型 业务模型描述了组织的业…

搜维尔科技:Xsens实时动作捕捉,驱动人形机器人操作!

搜维尔科技&#xff1a;http://www.souvr.comhttp://www.souvr.com实时动作捕捉&#xff0c;驱动人形机器人操作&#xff01; 搜维尔科技&#xff1a;Xsens实时动作捕捉&#xff0c;驱动人形机器人操作&#xff01;

方向导数和梯度

方向导数和梯度 1 导数的回忆2 偏导数及其向量形式偏导数的几何意义偏导数的向量形式 3 方向导数向量形式几何意义方向导数和偏导的关系 4 梯度5 梯度下降算法 1 导数的回忆 导数的几何意义如图所示&#xff1a; 当 P 0 P_{0} P0​点不断接近 P P P时&#xff0c;导数如下定义…

vue 中使用element-ui实现锚点定位表单

效果图&#xff1a; 代码&#xff1a; html代码&#xff1a; <div class"content-left"><el-tabs :tab-position"left" tab-click"goAnchor"><el-tab-pane v-for"(item,index) in anchorNameList"v-anchor-scroll:ke…

LeetCode 60.排序排列(dfs暴力)

给出集合 [1,2,3,...,n]&#xff0c;其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况&#xff0c;并一一标记&#xff0c;当 n 3 时, 所有排列如下&#xff1a; "123""132""213""231""312""321" 给定…

基于RSA的数字签名设计与实现

闲着没事把大三的实验发一下 这里用的技术和老师要求的略有不同但大体相同 1. RSA算法简介 公钥密码体制中,解密和加密密钥不同,解密和加密可分离,通信双方无须事先交换密钥就可建立起保密通信,较好地解决了传统密码体制在网络通信中出现的问题.另外,随着电子商务的发展,网络…

transformer模型学习路线_transformer训练用的模型

Transformer学习路线 完全不懂transformer&#xff0c;最近小白来入门一下&#xff0c;下面就是本菜鸟学习路线。Transformer和CNN是两个分支&#xff01;&#xff01;因此要分开学习 Transformer是一个Seq2seq模型&#xff0c;而Seq2seq模型用到了self-attention机制&#xf…

Python | Leetcode Python题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; class Solution:def isIsomorphic(self, s: str, t: str) -> bool:dicts Counter(s)dictt Counter(t) if list(dicts.values()) ! list(dictt.values()):return Falsefor i in range(len(s)):inds list(dicts.keys()).index(s…

【postgresql】 数据类型

数字类型 名字存储尺寸描述范围smallint2字节小范围整数-32768 ~32767integer4字节整数的典型选择-2147483648 ~ 2147483647bigint8字节大范围整数-9223372036854775808 ~ 9223372036854775807decimal可变用户指定精度&#xff0c;精确最高小数点前131072位&#xff0c;以及小…

python sklearn机械学习模型-回归

&#x1f308;所属专栏&#xff1a;【机械学习】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您…

使用SpringBoot整合Servlet

一、SpringBoot和Servlet的整合 1、用注解WebServlet配置Servlet映射 创建一个SpringBoot的web工程&#xff0c;在工程用创建一个Servlet 2、在SpringBoot的启动类上加注解ServletComponentScan 二、额外的方式 1、不使用WebServlet配置Servlet映射 创建一个SpringBoot工…

数据资产治理的智能化探索:结合云计算、大数据、人工智能等先进技术,探讨数据资产治理的智能化方法,为企业提供可靠、高效的数据资产解决方案,助力企业提升竞争力

一、引言 在信息化时代&#xff0c;数据已成为企业最重要的资产之一。随着云计算、大数据、人工智能等先进技术的飞速发展&#xff0c;数据资产治理面临着前所未有的机遇与挑战。本文旨在探讨如何结合这些先进技术&#xff0c;实现数据资产治理的智能化&#xff0c;为企业提供…

零知识学习之DPDK与RDMA(3)—— 认识DPDK(3)

接前一篇文章&#xff1a;零知识学习之DPDK与RDMA&#xff08;2&#xff09;—— 认识DPDK&#xff08;2&#xff09; 本文内容参考&#xff1a; 《Linux高性能网络详解 从DPDK、RDMA到XDP》 刘伟著 人民邮电出版社 https://blog.51cto.com/u_15301988/5181201 特此致谢&…

微软账户和本地账户有什么区别?如何切换登录账户?

Windows 操作系统是目前世界上比较流行的操作系统之一&#xff0c;在使用 Windows 系统的时候都需要我们进行登录&#xff0c;其中我们可以使用微软账户或者本地账户进行登录&#xff0c;那本地账户和微软账户有什么区别&#xff1f;下面就带大家了解一下微软账户和本地账户。 …

【Threejs进阶教程-着色器篇】2. Uniform的基本用法与Uniform的调试

Uniform的基本用法与Uniform的调试 关于本Shader教程优化上一篇的效果优化光栅栏高度让透明度和颜色变的更平滑pow()函数借助数学工具更好的理解函数 Unifoms简介编写uniforms修改片元着色器代码借助lil.gui调试uniforms使用uniform控制颜色继续在uniforms添加颜色在着色器中接…

git配置ssh-keygen -t rsa -c“xxxx@xxxx.com.cn出现Too many arguments.解决办法

git配置ssh-keygen -t rsa -c"xxxxxxxx.com.cn出现Too many arguments.解决办法 问题描述 配置Git公钥私钥时候输入命令ssh-keygen -t rsa -c"xxxxxxxx.com.cn出现Too many arguments. 解决办法&#xff1a; 提示输入的参数格式不正确&#xff0c;需要注意这几个地…

甄选版“论软件系统架构评估”,软考高级论文,系统架构设计师论文

论文真题 对于软件系统,尤其是大规模的复杂软件系统来说,软件的系统架构对于确保最终系统的质量具有十分重要的意义,不恰当的系统架构将给项目开发带来高昂的代价和难以避免的灾难。对一个系统架构进行评估,是为了:分析现有架构存在的潜在风险,检验设计中提出的质量需求,…