SpringDataJpa多表操作的实现

目录
  • Jpa表关系分析步骤
  • 关联关系的注解
    • @JoinColumn定义外键关联的字段名称
    • @OneToOne一对一关联关系
    • @OrderBy关联查询的时候的排序
    • @JoinTable关联关系表
    • @ManyToMany多对多

数据库中的表存在着多种关系,一对一,一对多,多对多

Jpa表关系分析步骤

开发过程中会有很多多表的操作,他们之间有着各种关系,在Jpa这种实现来了orm思想的框架中我们可以通过操作实体类来操作数据库,我们来连接下jap如何配置实体类来实现这种功能

  • 确定表之间的关系
  • 在数据库实现两个表的关系
  • 在实体类种描述两个表的关系
  • 配置数据库和实体类的关系映射

关联关系的注解

@OneToOne、@JoinColumn、@ManyToOne、@ManyToMany、@JoinTable、@OrderBy

@JoinColumn定义外键关联的字段名称

@Repeatable(JoinColumns.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JoinColumn {
    //目标表的字段名,必填
    String name() default "";
    //本实体的字段名,非必填,默认是本表ID
    String referencedColumnName() default "";
    //外键字段是否唯一
    boolean unique() default false;
    //外键字段是否允许为空
    boolean nullable() default true;
    //是否跟随一起新增
    boolean insertable() default true;
    //是否跟随一起更新
    boolean updatable() default true;

    String columnDefinition() default "";

    String table() default "";

    ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}

用法:@JoinColumn主要配合@OneToOne、@ManyToOne、@OneToMany一起使用,单独使用没有意义。@JoinColumn定义多个字段的关联关系。

@OneToOne一对一关联关系

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToOne {
    //关系目标实体,非必填,默认该字段的类型。
    Class targetEntity() default void.class;
    //cascade级联操作策略
    /*1.CascadeType.PERSIST级联新建
      2.CascadeType.REMOVE级联删除
      3.CascadeType.REFRESH级联刷新
      4.CascadeType.MERGE级联更新
      5.CascadeType.ALL四项全选
      6.默认,关系表不会产生任何影响*/
    CascadeType[] cascade() default {};
    //数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default FetchType.EAGER;
    h()defaultEAGER;//是否允许为空
    boolean optional() default true;
//关联关系被谁维护的。非必填,一般不需要特别指定。//注意:只有关系维护方才能操作两者的关系。被维护方即使设置了维护方属性进行存储也不会更新外键关联。1)mappedBy不能与@JoinColumn或者@JoinTable同时使用。2)mappedBy的值是指另一方的实体里面属性的字段,而不是数据库字段,也不是实体的对象的名字。既是另一方配置了@JoinColumn或者@JoinTable注解的属性的字段名称。
    String mappedBy() default "";
    //是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}

用法@OneToOne需要配合@JoinColumn一起使用。

举个例子使用@OneToOne和@JoinColumn注解

分析 一个学生对应一个班级,添加一个学生时同时添加班级

学生类

@Data
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String studentName;

    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "grade_id")
    private Grade grade;
}

班级类

@Data
@Entity
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String gradeName;

   /* @OneToOne(mappedBy = "grade")
    private Student student;*/
}

接口

public interface StudentRepository extends JpaRepository<Student,Integer> {
}

测试类

@Test
public void test1(){

    Grade grade = new Grade();
    grade.setGradeName("一年级");
    Student student = new Student();
    student.setStudentName("张三");
    student.setGrade(grade);
    studentRepository.save(student);
}

测试结果

这两个数据我用的一个是配置了一方关联,只在Student类里配置了班级信息,还有一条是配置了双向关联,Grade类里边被注释掉的部分,具体使用哪个,根据具体的业务需求

@OneToMany一对多& @ManyToOne多对一

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
    Class targetEntity() default void.class;
//cascade级联操作策略:(CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH、CascadeType.MERGE、CascadeType.ALL)
    CascadeType[] cascade() default {};
//数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default FetchType.LAZY;
//关系被谁维护,单项的。注意:只有关系维护方才能操作两者的关系。
    String mappedBy() default "";
//是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToOne {
    Class targetEntity() default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch() default FetchType.EAGER;

    boolean optional() default true;
}

@OneToMany一对多& @ManyToOne多对一的源码,FetchType一个是FetchType.LAZY;一个是 FetchType.EAGER;

实体类

现在实现一对多的例子,一个班有多个学生,新增班级时新增多个学生

@Entity
@Data
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String gradeName;

    @OneToMany(mappedBy = "grades",cascade = CascadeType.ALL)
    private List<Student>  students;

}
@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String studentName;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="grades_id")
    private Grade grades;
}

接口

public interface GradeRepository extends JpaRepository<Grade , Integer> {
}

测试类

@Test
public void test1(){
    Grade grade = new Grade();
    grade.setGradeName("一年级一班");
    ArrayList<Student> students = new ArrayList<>();

    Student student = new Student();
    student.setStudentName("张三");
    student.setGrades(grade);

    Student student1 = new Student();
    student1.setStudentName("李四");
    student1.setGrades(grade);

    students.add(student);
    students.add(student1);

    grade.setStudents(students);

    gradeRepository.save(grade);

}

结果

@OrderBy关联查询的时候的排序

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OrderBy {

    /***要排序的字段,格式如下:
    orderby_list::=orderby_item[,orderby_item]
    orderby_item::=[property_or_field_name][ASC|DESC]
    字段可以是实体属性,也可以数据字段,默认ASC。*/
    String value() default "";
}
@OneToMany(mappedBy = "grades",cascade = CascadeType.ALL)
@OrderBy("studentName DESC ")
private List<Student>  students;

@JoinTable关联关系表

@ManyToMany多对多

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToMany {
    Class targetEntity() default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch() default FetchType.LAZY;

    String mappedBy() default "";
}

@ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单向双向之分,单项双向和注解没有关系,只看实体类之间是否相互引用。主要注意的是当用到@ManyToMany的时候一定是三张表。

a案例

一个年级有多个老师,一个老师管多个年级

实体类

@Entity
@Data
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer gradeid;
    private String gradeName;
    //配置年级和老师之间的多对多关系
    //1.声明多对多的关系@ManyToMany(targetEntity = Teacher.class)
    //2.配置中间表
    /* @JoinTable(name = "grade_teacher", 中间表表名
            joinColumns = @JoinColumn(name = "grade_id" 外键名
            ,referencedColumnName = "gradeid"参照的主表的主键名
            ),
            中间表字段名,在当前表的外键
            inverseJoinColumns = @JoinColumn(name = "tecacher_id",referencedColumnName = "teacherid"))
            */

    @ManyToMany(targetEntity = Teacher.class,cascade = CascadeType.ALL)//对方的实体字节码
    //中间表名,
    @JoinTable(name = "grade_teacher",
    //外键名,
            joinColumns = @JoinColumn(name = "grade_id",referencedColumnName = "gradeid"),
            inverseJoinColumns = @JoinColumn(name = "tecacher_id",referencedColumnName = "teacherid"))
    private List<Teacher> teachers;
}
@Data
@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer teacherid;
    private String  teacherName;

    @ManyToMany(mappedBy = "teachers")
    private List<Grade> grades;
}

接口

public interface GradeRepository extends JpaRepository<Grade , Integer> {
}

测试类

@Test
@Transactional
@Commit()
public void test2(){
    //配置两个年级
    Grade grade = new Grade();
    grade.setGradeName("一年级");
    Grade grade2 = new Grade();
    grade2.setGradeName("二年级");

    //创建3个老师
    Teacher teacher = new Teacher();
    teacher.setTeacherName("张老师");
    Teacher teacher2 = new Teacher();
    teacher2.setTeacherName("王老师");
    Teacher teacher3 = new Teacher();
    teacher3.setTeacherName("李老师");

    //给一年级赛3个老师
    ArrayList<Teacher> teachers = new ArrayList<>();
    teachers.add(teacher);
    teachers.add(teacher2);
    teachers.add(teacher3);
    grade.setTeachers(teachers);

    //给2年级赛2个老师
    ArrayList<Teacher> teachers1 = new ArrayList<>();
    teachers1.add(teacher2);
    teachers1.add(teacher3);
    grade2.setTeachers(teachers1);

    gradeRepository.save(grade);
    gradeRepository.save(grade2);
}

测试结果

到此这篇关于SpringDataJpa多表操作的实现的文章就介绍到这了,更多相关SpringDataJpa多表操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring Data JPA 实现多表关联查询的示例代码

    多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,这里介绍第二种方式. 一.一对一映射 实体 UserInfo :用户. 实体 Address:家庭住址. 这里通过外键的方式(一个实体通过外键关联到另一个实体的主键)来实现一对一关联. 实体类 1.实体类 UserInfo.java package com.johnfnash.learn.domain; import java.io.Ser

  • SpringDataJpa多表操作的实现

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

  • springdata jpa单表操作crud的实例代码详解

    1. 项目搭建 使用boot整合,导入springdata jap, mysql 驱动,lombok,web. 1.1 配置 # boot add jpa, oh~ crud in single table server: port: 8888 spring: # datasource datasource: username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://

  • PHP数据库表操作的封装类及用法实例详解

    本文实例讲述了PHP数据库表操作的封装类及用法.分享给大家供大家参考,具体如下: 数据库表结构: CREATE TABLE `test_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL, `password` varchar(45) NOT NULL, `nickname` varchar(45) NOT NULL, `r` tinyint(4) NOT NULL, PRIMARY KEY

  • C# 注册表 操作实现代码

    其中第二级目录包含了五个预定义主键分别是:HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS,HKEY_CURRENT_CONFIG. 下面我们来分别解释这5个类的作用 HKEY_CLASSES_ROOT该主键包含了文件的扩展名和应用程序的关联信息以及Window Shell和OLE用于储存注册表的信息.该主键下的子键决定了在WINDOWS中如何显示该类文件以及他们的图标,该主键是从HKEY_LCCAL_MACHIN

  • MySQL使用游标批量处理进行表操作

    一.概述 本章节介绍使用游标来批量进行表操作,包括批量添加索引.批量添加字段等.如果对存储过程.变量定义.预处理还不是很熟悉先阅读我前面写过的关于这三个概念的文章,只有先了解了这三个概念才能更好的理解这篇文章. 理解MySQL变量和条件:http://www.jb51.net/article/81375.htm 理解Mysql prepare预处理语句:http://www.jb51.net/article/81378.htm 理解MySQL存储过程和函数:http://www.jb51.net

  • c#注册表操作类分享

    复制代码 代码如下: /// <summary>/// 注册表基项静态域/// /// 主要包括:/// 1.Registry.ClassesRoot 对应于HKEY_CLASSES_ROOT主键/// 2.Registry.CurrentUser 对应于HKEY_CURRENT_USER主键/// 3.Registry.LocalMachine 对应于 HKEY_LOCAL_MACHINE主键/// 4.Registry.User 对应于 HKEY_USER主键/// 5.Registry.

  • Hibernate单表操作实例解析

    单一主键 assigned:由Java应用程序负责生成(即手工的赋值) native:由底层的数据库自动的生成标示符,如果是MySQL就是auto_increment,如果是Oracle就是sequence,等等 操作的时候还是需要结合hibernate.cfg.xml文件的,因为数据库中的hbm2ddl.auto属性如果是update的时候,设置为主键自增是可以的:但是如果是create的时候,第二次如果不手工的改变,恐怕就要出BUG了. 基本类型 一般来说,按照Java的数据类型进行操作就可

  • PHP框架Laravel中使用UUID实现数据分表操作示例

    本文实例讲述了PHP框架Laravel中使用UUID实现数据分表操作.分享给大家供大家参考,具体如下: UUID UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的. 说的简单点,它就是通过一个规则(如:业务标识号+年月日+当日自增数字格式化)生成的一个具有唯一性的辨识资讯.用于关联我们的一些额数据和资讯. 实例 之前在做一个项目的时候用到这个东西,现在我就用Laravel框架写一个简单的demo 前端form表单 <!DOCTYPE html> <html&g

  • hibernate多表操作实例代码

    多表操作之多对多关系简介 思路就是: 在数据库底层通过添加中间表来指定关联关系. 在双方的实体中添加一个保存对方的集合 在双方的配置文件中使用set标签和many-to-many标签来进行关联关系的配置.即可完成! 调用Hibernate的相关的API,操作就行了. 需要注意的地方 首先是数据库中表的创建 这里有一个小例子: 多对多的核心表,第三方表.table: create table thrid( one_id int not null, two_id int not null, cons

  • django框架自定义用户表操作示例

    本文实例讲述了django框架自定义用户表操作.分享给大家供大家参考,具体如下: django中已经给我生成默认的User表,其中的字段已经可以满足我们的日常需求. 但有时候,我们需要更多的字段,我们就可以自定义.来替换django自带的User表. models.py from django.contrib.auth.models import AbstractUser class UserProfile(AbstractUser): nick_name = models.CharField(

随机推荐