This is the fourth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

Tables in a database have multiple relationships, one-to-one, one-to-many, many-to-many

Jpa table relationship analysis steps

During the development process, there will be a lot of multi-table operations, and they have various relationships. In THE FRAMEWORK of Jpa, which implements the ORM idea, we can operate the database by operating on the entity class. How does JAP configure the entity class to achieve this function

  1. Determine the relationships between tables
  2. Implement the relationship between two tables in the database
  3. Describes the relationship between two tables in the entity class
  4. Configure the relational mapping between database and entity classes

Annotations of associated relationships

@oneToOne, @JoinColumn, @ManyToOne, @ManyTomany, @JoinTable, @OrDerby

@joinColumn Defines the field name associated with the foreign key
@Repeatable(JoinColumns.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JoinColumn {
    // Field name of the target table, mandatory
    String name(a) default "";
    // The field name of this entity. The default value is this table ID
    String referencedColumnName(a) default "";
    // Whether the foreign key field is unique
    boolean unique(a) default false;
    // Whether the foreign key field can be empty
    boolean nullable(a) default true;
    // Whether to add it together
    boolean insertable(a) default true;
    // Whether to follow along with the update
    boolean updatable(a) default true;

    String columnDefinition(a) default "";

    String table(a) default "";

    ForeignKey foreignKey(a) default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
Copy the code

Usage: @joinColumn is mainly used together with @onetoone, @manytoOne and @onetomany. It is meaningless to use it alone. @joinColumn Defines the association between multiple columns.

OneToOne one-to-one relationship
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToOne {
    // Relationship target entity, optional, default type of this field.
    Class targetEntity(a) default void.class;
    //cascade Cascade operation policy
    Cascadetype. REMOVE Cascading deletion 3. Cascadetype. REFRESH cascading REFRESH 4 CascadeType.ALL choose 6. By default, relational tables have no effect */
    CascadeType[] cascade() default {};
    // Data can be obtained by means of EAGER(immediate loading)/LAZY(LAZY loading).
    FetchType fetch(a) default FetchType.EAGER;
    h()defaultEAGER;// Whether to allow null
    boolean optional(a) default true;
// The relationship is maintained by whom. This field is not required. // Note: Only the maintainer can manipulate the relationship between the two. The maintained party does not update the foreign key association even if the maintainer property is set for storage. 1) mappedBy cannot be used together with @joinColumn or @JoinTable. 2) The value of mappedBy refers to the field of the property in the other party's entity, not the database field, and not the name of the entity's object. It is the field name of the @JoinColumn or @JoinTable attribute configured by the other party.
    String mappedBy(a) default "";
    // Whether to perform cascading deletion. Same effect as cascadeType.remove. If one of the two configurations is configured, it will be automatically deleted in cascading mode
    boolean orphanRemoval(a) default false;
}
Copy the code

Usage @oneToOne must be used together with @joinColumn.

An example is using @onetoOne and @JoinColumn annotations

Analyze a student for a class, add a class when adding a student

Students in class
@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;
}
Copy the code
The class and grade class
@Data
@Entity
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String gradeName;

   /* @OneToOne(mappedBy = "grade") private Student student; * /
}
Copy the code
interface
public interface StudentRepository extends JpaRepository<Student,Integer> {
}
Copy the code
The test class
@Test public void test1(){ Grade grade = new Grade(); Grade. SetGradeName (" grade 1 "); Student student = new Student(); Student. SetStudentName (" zhang "); student.setGrade(grade); studentRepository.save(student); }Copy the code
The test results

One of the two data I used is to configure one party association, and only the class information is configured in the Student class. The other one is to configure the bidirectional association, which part is annotated out in the Grade class. The specific use depends on the specific business needs

@onetomany OneToMany & @manytoone ManyToOne
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
    Class targetEntity(a) default void.class;
//cascade cascade operation policies :(cascadetype. PERSIST, cascadetype. REMOVE, cascadetype. REFRESH, cascadetype. MERGE, cascadetype. ALL)
    CascadeType[] cascade() default {};
// Data can be obtained by means of EAGER(immediate loading)/LAZY(LAZY loading).
    FetchType fetch(a) default FetchType.LAZY;
// Who is maintaining the relationship? Note: Only the relationship keeper can manipulate the relationship.
    String mappedBy(a) default "";
// Whether to perform cascading deletion. Same effect as cascadeType.remove. If one of the two configurations is configured, it will be automatically deleted in cascading mode
    boolean orphanRemoval(a) default false;
}
Copy the code
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToOne {
    Class targetEntity(a) default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch(a) default FetchType.EAGER;

    boolean optional(a) default true;
}
Copy the code

@onetomany one-to-many & @manyToOne many-to-one source, FetchType a FetchType.LAZY; One is FetchType. EAGER;

Entity class

Now implement a one-to-many example where there are multiple students in a class, and each new class has more students

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

}
Copy the code
@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;
}
Copy the code
interface
public interface GradeRepository extends JpaRepository<Grade , Integer> {
}
Copy the code
The test class
@Test public void test1(){ Grade grade = new Grade(); Grade. SetGradeName (" Class 1, Grade 1 "); ArrayList<Student> students = new ArrayList<>(); Student student = new Student(); Student. SetStudentName (" zhang "); student.setGrades(grade); Student student1 = new Student(); Student1. SetStudentName (" li si "); student1.setGrades(grade); students.add(student); students.add(student1); grade.setStudents(students); gradeRepository.save(grade); }Copy the code
The results of

@orderby The sort when associated with a query
@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] fields can be entity attributes, can also be data fields, ASC by default. */ String value() default ""; }Copy the code
@OneToMany(mappedBy = "grades",cascade = CascadeType.ALL)
@OrderBy("studentName DESC ")
private List<Student>  students;
Copy the code
@joinTable Indicates the association table
@ ManyToMany many-to-many
@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 "";
}
Copy the code

@manytomany means many-to-many, and it can be one-way and two-way just like @onetoone and @manytoOne. One-way and two-way has nothing to do with annotations, but only whether entity classes refer to each other. The main thing to notice is that @manytomany must have three tables.

A case study

There are multiple teachers in one grade, and one teacher supervises multiple grades

Entity class
@Entity @Data public class Grade { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer gradeid; private String gradeName; Many-to-many relationship @manytomany (targetEntity = teacher.class) //2 /* @joinTable (name = "grade_teacher", JoinColumns = @joinColumn (name = "grade_ID" foreign key name,referencedColumnName = "gradeID" primary key name of primary table) InverseJoinColumns = @joinColumn (name = "tecacher_id",referencedColumnName = "teacherID ")) */ @manytomany (targetEntity = teacher.class,cascade = cascadeType.all) @jointable (name = "grade_teacher", // foreign key,  joinColumns = @JoinColumn(name = "grade_id",referencedColumnName = "gradeid"), inverseJoinColumns = @JoinColumn(name = "tecacher_id",referencedColumnName = "teacherid")) private List<Teacher> teachers; }Copy the code
@Data
@Entity
public class Teacher {

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

    @ManyToMany(mappedBy = "teachers")
    private List<Grade> grades;
}
Copy the code
interface
public interface GradeRepository extends JpaRepository<Grade , Integer> {
}
Copy the code
The test class
@Test
@Transactional
@Commit()
public void test2(a){
    // Configure two grades
    Grade grade = new Grade();
    grade.setGradeName("First grade");
    Grade grade2 = new Grade();
    grade2.setGradeName("Second grade");

    // Create 3 teachers
    Teacher teacher = new Teacher();
    teacher.setTeacherName("Miss Zhang");
    Teacher teacher2 = new Teacher();
    teacher2.setTeacherName("Miss Wang");
    Teacher teacher3 = new Teacher();
    teacher3.setTeacherName("Miss Li");

    // There are three teachers in the first grade
    ArrayList<Teacher> teachers = new ArrayList<>();
    teachers.add(teacher);
    teachers.add(teacher2);
    teachers.add(teacher3);
    grade.setTeachers(teachers);


    // Give two teachers to grade 2
    ArrayList<Teacher> teachers1 = new ArrayList<>();
    teachers1.add(teacher2);
    teachers1.add(teacher3);
    grade2.setTeachers(teachers1);

    gradeRepository.save(grade);
    gradeRepository.save(grade2);
}
Copy the code
The test results

End and spend