Spring Data Jpa (二)

注解详解

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "authors")
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", length = 100, nullable = false)
    private String name;

    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
    private List<Book> books;

    // Constructors, getters, setters, and other methods

}

@Entity
@Table(name = "books")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "title", length = 200, nullable = false)
    private String title;

    @ManyToOne
    @JoinColumn(name = "author_id", referencedColumnName = "id")
    private Author author;

    // Constructors, getters, setters, and other methods

}

这里有一些关键点说明:

  1. Author 类:
  • @Entity: 表示这是一个JPA实体类。
  • @Table: 指定数据库表的名称。
  • @Id: 标识主键字段。
  • @GeneratedValue: 指定主键生成策略。
  • @Column: 指定属性与数据库表列的映射关系。
  • @OneToMany: 声明一对多关系,指定了mappedBy表示关系由Book类的author属性来维护。
  1. Book类:
  • @Entity: 表示这是一个JPA实体类。
  • @Table: 指定数据库表的名称。
  • @Id: 标识主键字段。
  • @GeneratedValue: 指定主键生成策略。
  • @Column: 指定属性与数据库表列的映射关系。
  • @ManyToOne: 声明多对一关系。
  • @JoinColumn: 指定关联列的信息。

@Table

@Table 注解是用于配置实体与数据库表之间映射关系的注解。它提供了一些属性,可以用于定义表的各种属性,如表名、索引、唯一约束等。
以下是 @Table 注解的一些常用属性和详细解释:

  1. name属性:
  • 作用: 指定数据库表的名称。
  • 示例:
@Entity
@Table(name = "authors")
public class Author {
    // ...
}
  • 说明: 在上例中,@Table(name = "authors") 表示将 Author 实体映射到数据库中的 "authors" 表。
  1. catalogschema 属性:
  • 作用: 用于指定数据库的 catalog 和 schema。
  • 示例:
@Entity
@Table(name = "authors", catalog = "library_db", schema = "public")
public class Author {
    // ...
}
  • 说明: 在上例中,catalog 属性指定了数据库的 catalog(数据库目录),schema 属性指定了数据库的 schema(数据库模式)。
  1. uniqueConstraints 属性:
  • 作用: 用于定义表上的唯一约束。
  • 示例:
@Entity
@Table(name = "authors", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class Author {
    // ...
}
  • 说明: 在上例中,uniqueConstraints 属性指定了在 "authors" 表上创建一个唯一约束,该约束包含一个名为 "email" 的列。
  1. indexes 属性:
  • 作用: 用于定义表上的索引。
  • 示例:
@Entity
@Table(name = "authors", indexes = @Index(columnList = "last_name"))
public class Author {
    // ...
}
  • 说明: 在上例中,indexes 属性指定了在 "authors" 表上创建一个索引,该索引包含一个名为 "last_name" 的列。
  1. *schema` 属性:
  • 作用: 用于指定数据库表的 schema。
  • 示例:
@Entity
@Table(name = "authors", schema = "public")
public class Author {
    // ...
}
  • 说明: 在上例中,schema 属性指定了数据库表的 schema(数据库模式)。

@Column 注解是用于配置实体属性与数据库表列之间映射关系的注解。它提供了一些属性,可以用于定义列的各种属性,如列名、长度、是否可为空等。

@Column

  1. name 属性:
  • 作用: 指定数据库表列的名称。
  • 示例:
@Entity
public class Author {
    @Column(name = "full_name")
    private String fullName;
    // ...
}
  • 说明: 在上例中,@Column(name = "full_name") 表示将 Author 实体的 fullName 属性映射到数据库表的 "full_name" 列。
  1. **nullable**** 属性:**
  • 作用: 指定列是否允许为null。
  • 示例:
@Entity
public class Author {
    @Column(nullable = false)
    private String fullName;
    // ...
}
  • 说明: 在上例中,@Column(nullable = false) 表示 fullName 列不允许为null。
  1. unique 属性:
  • 作用: 指定列的值是否唯一。
  • 示例:
@Entity
public class Author {
    @Column(unique = true)
    private String email;
    // ...
}
  • 说明: 在上例中,@Column(unique = true) 表示 email 列的值必须是唯一的。
  1. length属性:
  • 作用: 指定列的长度。
  • 示例:
@Entity
public class Author {
    @Column(length = 50)
    private String fullName;
    // ...
}
  • 说明: 在上例中,@Column(length = 50) 表示 fullName 列的长度为50。
  1. precisionscale 属性:
  • 作用: 用于指定精度和小数位数(仅对浮点型有效)。
  • 示例:
@Entity
public class Book {
    @Column(precision = 10, scale = 2)
    private BigDecimal price;
    // ...
}
  • 说明: 在上例中,@Column(precision = 10, scale = 2) 表示 price 列的精度为10,小数位数为2。
  1. **columnDefinition**** 属性:**
  • 作用: 允许通过 SQL 片段定义完整的列定义。可拼接建表语句
  • 示例:
@Entity
public class Book {
    @Column(columnDefinition = "TEXT")
    private String description;
    @Column(name = "user",columnDefinition = "VARCHAR ( 32 ) COMMENT '操作人'")
    private String user;
    // ...
}
  • 说明: 在上例中,@Column(columnDefinition = "TEXT") 表示 description 列的数据库定义为TEXT类型。

@Id

  1. 基本使用:
@Entity
public class Author {
    @Id
    private Long id;
    // ...
}

在上例中,@Id 注解标识了 Author 实体类的 id 字段作为主键。

  1. 生成策略 (**@GeneratedValue**):
@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // ...
}

通常与 @GeneratedValue 注解一起使用,用于指定主键的生成策略。GenerationType.IDENTITY 表示使用数据库的自增长策略。

  1. 复合主键(Composite Primary Key):
@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Id
    private String isbn;
    // ...
}

在一些情况下,实体的主键可能由多个字段组成,这时可以在多个字段上都使用 @Id 注解,表示复合主键。

  1. 主键的类型:
@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // ...
}

主键可以是任意 Java 数据类型,例如 LongStringint 等。通常,主键类型应该是可序列化的,并且不可变。

  1. 自定义主键生成器:
@Entity
public class Book {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;
    // ...
}

如果需要使用自定义的主键生成器,可以通过 @GeneratedValue@GenericGenerator 注解来配置。

@OneToOne

@OneToOne 是 JPA 中用于建立一对一关联关系的注解。它用于标注两个实体之间的一对一关系,其中一个实体(称为拥有方)包含对另一个实体(称为被拥有方)的引用。这个注解通常用在两个实体类中的成员变量上,表示两个实体之间的关联。

拥有方(Owner):

@Entity
@Table(name = "member")
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "member", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private MemberInfo memberInfo;

    // other fields, getters, setters, etc.
}

被拥有方(Inverse):

@Entity
@Table(name = "member_info")
public class MemberInfo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @JoinColumn(name = "member_id")
    private Member member;

    // other fields, getters, setters, etc.
}

在上面的示例中:

  • Member 实体是拥有方,通过 @OneToOne 注解和 mappedBy 属性表示这是一对一关系,并指定了被拥有方是 memberInfo
  • MemberInfo 实体是被拥有方,通过 @OneToOne 注解和 @JoinColumn 注解表示这是一对一关系,指定了关联的外键列为 member_id

注意事项:

  • 一对一关系中,拥有方一般是含有外键的一方,而被拥有方则是被引用的一方。
  • 使用 mappedBy 属性来指定被拥有方的属性,表示关系的维护交由被拥有方来负责。在上述例子中,Member 中的 memberInfo 属性负责关系的维护。
  • @JoinColumn 注解用于指定关联关系的外键列的名称。

在实际应用中,一对一关系通常用于建模特殊的业务场景,例如,一个实体与另一个实体存在唯一对应关系,或者某个实体的一部分信息存储在另一个实体中等。

@OneToMany

@OneToMany 注解用于在JPA实体类中建立一对多的关系,表示一个实体对象包含多个另一种实体对象。这种关系通常用于描述父实体与子实体之间的关联,其中一个父实体对应多个子实体。

  1. 基本使用:
@Entity
public class Author {
    @OneToMany(mappedBy = "author")
    @BatchSize(size = 10) // 每次加载10个关联实体
    private List<Book> books;
    // ...
}

在上例中,@OneToMany 注解表示 Author 实体类拥有多个 Book 实体。mappedBy 属性指定了在 Book 实体类中维护关联关系的属性名为 "author"。

  1. **cascade**** 属性:**
@Entity
public class Author {
    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
    private List<Book> books;
    // ...
}

cascade 属性用于指定级联操作的类型。在上例中,CascadeType.ALL 表示对 Author 实体的操作将级联到其关联的所有 Book 实体。

  1. **fetch**** 属性:**
@Entity
public class Author {
    @OneToMany(mappedBy = "author", fetch = FetchType.LAZY)
    private List<Book> books;
    // ...
}

fetch 属性用于指定关联关系的加载策略。FetchType.LAZY 表示懒加载,只有在访问 books 属性时才会加载关联的 Book 实体。

  1. **targetEntity**** 属性:**
@Entity
public class Author {
    @OneToMany(mappedBy = "author", targetEntity = Book.class)
    private List<Book> books;
    // ...
}

targetEntity 属性用于指定关联的实体类型。在上例中,指定了关联的实体类型为 Book

  1. **orphanRemoval**** 属性:**
@Entity
public class Author {
    @OneToMany(mappedBy = "author", orphanRemoval = true)
    private List<Book> books;
    // ...
}

orphanRemoval 属性用于指定是否移除孤儿对象。如果设置为 true,当从 books 列表中移除 Book 实体时,该 Book 实体将被从数据库中删除。

  1. **mappedBy**** 属性:**
@Entity
public class Book {
    @ManyToOne
    //@JoinColumn用于设置,关联的外键约束的字段(外键配置)。
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

@OneToMany 注解中,mappedBy 属性用于指定在关联的另一方实体中维护关联关系的属性。在上例中,mappedBy = "author" 表示关联关系由 Book 实体的 author 属性维护。

@ManyToOne

@ManyToOne 注解用于在JPA实体类中建立多对一的关系,表示一个实体对象属于另一种实体对象。这种关系通常用于描述子实体与父实体之间的关联,其中多个子实体对应一个父实体。

  1. 基本使用:
@Entity
public class Book {
    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

在上例中,@ManyToOne 注解表示 Book 实体类属于一个 Author 实体。@JoinColumn 注解用于指定关联的外键列名为 "author_id"。

  1. **optional**** 属性:**
@Entity
public class Book {
    @ManyToOne(optional = false)
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

optional 属性用于指定关联的实体是否可以为null。如果设置为 false,表示 Book 实体必须关联一个非空的 Author 实体。

  1. **fetch**** 属性:**
@Entity
public class Book {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

fetch 属性用于指定关联关系的加载策略。FetchType.LAZY 表示懒加载,只有在访问 author 属性时才会加载关联的 Author 实体。

  1. **targetEntity**** 属性:**
@Entity
public class Book {
    @ManyToOne(targetEntity = Author.class)
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

targetEntity 属性用于指定关联的实体类型。在上例中,指定了关联的实体类型为 Author

  1. **cascade**** 属性:**
@Entity
public class Book {
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "author_id")
    private Author author;
    // ...
}

cascade 属性用于指定级联操作的类型。在上例中,CascadeType.ALL 表示对 Book 实体的操作将级联到其关联的 Author 实体。

  1. **mappedBy**** 属性:**
@Entity
public class Author {
    @OneToMany(mappedBy = "author")
    private List<Book> books;
    // ...
}

@ManyToOne 注解中,mappedBy 属性用于指定在关联的另一方实体中维护关联关系的属性。在上例中,mappedBy = "author" 表示关联关系由 Author 实体的 books 属性维护。

@ManyToMany

@ManyToMany 是 JPA 中用于建立多对多关联关系的注解。多对多关系表示两个实体之间的关系是多对多的,一个实体可以与多个其他实体关联,同样,一个实体也可以被多个其他实体关联。

实体类1:

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses = new HashSet<>();

    // other fields, getters, setters, etc.
}

@JoinTable 注解用于定义多对多关联关系的关联表信息。在多对多关系中,由于涉及到中间表来存储关联关系,因此需要使用 @JoinTable 注解来指定中间表的相关信息。

  • name = "student_course":指定关联表的名称为 "student_course"。
  • joinColumns = @JoinColumn(name = "student_id"):指定关联表中与当前实体(Student 实体)关联的外键列的信息。在这里,student_id 列将用于关联 Student 实体。
  • inverseJoinColumns = @JoinColumn(name = "course_id"):指定关联表中与关联实体(Course 实体)关联的外键列的信息。在这里,course_id 列将用于关联 Course 实体。

简而言之,@JoinTable 注解定义了关联表的名称和与两个实体关联的外键列的信息。在这个例子中,"student_course" 表将包含 student_idcourse_id 两列,用于关联 Student 实体和 Course 实体。

实体类2:

@Entity
@Table(name = "course")
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "courses")
    private Set<Student> students = new HashSet<>();

    // other fields, getters, setters, etc.
}

在上述示例中:

  • Student 实体和 Course 实体之间建立了多对多的关系,Student 中的 courses 属性表示一个学生可以选修多门课程,而 Course 中的 students 属性表示一门课程可以被多个学生选修。
  • 使用 @ManyToMany 注解来表示多对多关系,cascade = CascadeType.ALL 表示级联操作,即当对一个实体进行操作时,关联的实体也会相应地进行相同的操作。
  • 使用 @JoinTable 注解指定中间表的名称和关联的外键列。
  • Course 实体中使用 mappedBy 属性指定关联关系的被拥有方,这是因为关系的维护交由 Student 实体来处理。

注意事项:

  • 多对多关系通常需要中间表来存储两个实体的关联关系,这个中间表称为关联表(Join Table)。
  • @JoinTable 注解用于指定关联表的信息,包括表的名称、关联的外键列等。
  • mappedBy 属性用于指定关联关系的被拥有方,表示关系的维护交由被拥有方来负责。
  • 在查询时,可以通过 @Query 注解、QueryDSL 或者使用内置的方法来进行多对多关系的查询。

@Embedded

@Embeddable 注解是 JPA 中用于标识可嵌入对象(Embeddable)的注解。嵌入对象是将一个对象的属性嵌入到另一个对象中,使得这些属性不再形成一个独立的实体,而是成为包含它们的实体的一部分。

  1. 标识为可嵌入对象:
  • 使用 @Embeddable 注解标识一个类,表示该类的实例可以被嵌入到其他实体中。
@Embeddable
public class Address {
    @Column(name = "street")
    private String street;

    @Column(name = "city")
    private String city;
}
  1. 嵌入对象的属性:
  • @Embeddable 标识的类中,定义需要嵌入的属性,可以使用 @Column 注解进行属性的详细配置。
  1. 嵌入到实体中:
  • 在包含该嵌入对象的实体类中使用 @Embedded 注解引入嵌入对象。
  • 嵌入对象可以在多个实体中进行复用,减少了实体类的冗余代码。
@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Embedded
    private Address address;
}
  1. 嵌入对象的属性在实体表中:
  • 当实体类中引入了嵌入对象后,嵌入对象的属性将成为实体表的一部分,而不再形成独立的表。
CREATE TABLE Person (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    street VARCHAR(255),
    city VARCHAR(50)
);

通过使用 @Embeddable 注解和@Embedded注解,可以将一组属性视为一个整体,并嵌入到其他实体中,提高了实体模型的灵活性和可维护性。

@Transient

使用 @Transient 注解标识实体类中的字段或方法,表示这些属性不会被持久化到数据库。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容