文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JPA 注解及主键生成策略使用指南

2023-08-16 17:10

关注

JPA 注解

Entity 常用注解

参考:JPA & Spring Data JPA学习与使用小记

指定对象与数据库字段映射时注解的位置:如@Id、@Column等注解指定Entity的字段与数据库字段对应关系时,注解的位置可以在Field(属性)或Property(属性的get方法上),两者统一用其中一种,不能两者均有。推荐用前者。

@Entity、@Table

@Entity(必需)

标注在实体类上。

映射实体类。指出该 Java 类为实体类,将映射到指定的关系数据库表。

应用了此注解后,将会自动将类名映射作为数据库表名、将类内的字段名映射为数据库表的列名。映射策略默认是按驼峰命名法拆分将类名或字段名拆分成多部分,然后以下划线连接,如StudentEntity -> student_entity、studentName -> student_name。若不按默认映射,则可通过@Table、@Column 指定,见下面。


@Table(可选)

标注在实体类上。

映射数据库表名。当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用


@DynamicInsert、@DynamicUpdate

@DynamicInsert(可选)

标注在实体类上。

设置为 true,表示 insert 对象的时候,生成动态的 insert 语句,如果这个字段的值是 null 就不会加入到 insert 语句中,默认 false


@DynamicUpdate(可选)

标注在实体类上。

注意:


@Id、@GeneratedValue

@Id(必需)

标注在实体类成员变量或 getter 方法之上。

映射生成主键。用于声明一个实体类的属性映射为数据库的一个主键列。

若同时指定了下面的 @GeneratedValue 则存储时会自动生成主键值,否则在存入前用户需要手动为实体赋一个主键值。

主键值类型可以是:

指定联合主键,有 @IdClass、@EmbeddedId 两种方法。


@GeneratedValue

@GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。

默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment


@Column、@Basic、@Transient

@Column(可选)

标注在实体类成员变量或 getter 方法之上。

映射表格列。当实体的属性与其映射的数据库表的列不同名时需要使用 @Column 标注说明。

类的字段名在数据库中对应的字段名可以通过此注解的name属性指定,不指定则默认为将属性名按驼峰命名法拆分并以下划线连接,如 createTime 对应 create_time

**注意:**即使name的值中包含大写字母,对应到db后也会转成小写,如@ Column(name="create_Time") 在数据库中字段名仍为create_time。可通过SpringBoot配置参数【spring.jpa.hibernate.naming.physical-strategy】配置对应策略,如指定name值是什么,数据库中就对应什么名字的列名。默认值为:【org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy】

@Column注解一共有10个属性,这10个属性均为可选属性,各属性含义分别如下:


@Basic(可选)

表示一个简单的属性到数据表的字段的映射,对于没有任何标注的属性或getter方法,默认标注为 @Basic


@Transient:忽略属性

定义暂态属性。表示该属性并非一个到数据库表的字段的映射,ORM 框架将忽略该属性。

如果一个属性并非数据库表的字段映射,就必须将其标识为 @Transient,否则ORM 框架默认为其注解 @Basic,例如工具方法不需要映射。


@Temporal:时间日期精度

标注在实体类成员变量或getter方法之上。可选。

在 JavaAPI 中没有定义 Date 类型的精度,而在数据库中表示 Date 类型的数据类型有 Date(年月日),Time(时分秒),TimeStamp(年月日时分秒) 三种精度,进行属性映射的时候可以使用 @Temporal 注解调整精度。

目前此注解只能用于修饰JavaAPI中的【java.util.Date】、【java.util.Calendar】类型的变量,TemporalType 取 DATE、TIME、TIMESTAMP 时在MySQL中分别对应的 DATE、TIME、DATETIME 类型。

示例:

@Temporal(TemporalType.TIMESTAMP)    @CreationTimestamp //org.hibernate.annotations.CreationTimestamp,用于在JPA执行insert操作时自动更新该字段值    @Column(name = "create_time", updatable=false )//为防止手动set,可设false以免该字段被更新    private Date createTime;    @Temporal(TemporalType.TIMESTAMP)    @UpdateTimestamp //org.hibernate.annotations.UpdateTimestamp,用于在JPA执行update操作时自动更新该字段值    private Date updateTime;

时间日期自动更新:

Hibernate 的注解:

​ @CreationTimestamp(创建时间)、@UpdateTimestamp(更新时间)

​ 用法:在时间日期类型属性上加上注解即可

SpringDataJPA 的注解:(可参阅https://blog.csdn.net/tianyaleixiaowu/article/details/77931903)

​ @CreatedDate(创建时间)、@LastModifiedDate(更新时间)、@CreatedBy、@LastModifiedBy

用法:

  1. 在实体类加上注解 @EntityListeners(AuditingEntityListener.class)
  2. 在启动类上加上注解 @EnableJpaAuditing
  3. 在实体类中属性中加上面四种注解

示例:

@Data@MappedSuperclass@EntityListeners(AuditingEntityListener.class)public abstract class BaseEntity {    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    protected Integer id;        // 创建时间    @CreatedDate    @Column(name = "create_time", updatable=false )//为防止手动set,可设false以免该字段被更新    private Long createTime;        // 更新时间    @LastModifiedDate    @Column(name = "update_time")    private Long updateTime;}

其他注解

@MappedSuperClass:共有字段超类

标注在实体类上。

共有字段超类中声明了各 Entity 共有的字段,即数据库中多表中共有的字段,如 create_time、update_time、id 等。

标注为 @MappedSuperclass 的类将不是一个完整的实体类,将不会映射到数据库表,但是其属性都将映射到其子类的数据库字段中。

标注为 @MappedSuperclass 的类不能再标注 @Entity 或 @Table 注解,也无需实现序列化接口。

允许多级继承

注解的类继承另一个实体类或标注 @MappedSuperclass 类,可以使用 @AttributeOverride 或 @AttributeOverrides 注解重定义其父类属性映射到数据库表中字段。


@IdClass:指定联合主键类

标注在实体类上。

指定联合主键类。如:@IdClass(StudentExperimentEntityPK.class)

主键类 StudentExperimentEntityPK 需要满足:

示例:

@Data@Entity@Table(name = "customer_course")@IdClass(CustomerCourseEntityPK.class)// 指定联合主键类public class CustomerCourseEntity {    @Id    @Column(name = "customer_id", length = ColumnLengthConstrain.LEN_ID_MAX)    private String customerId;        @Id    @Column(name = "course_id", length = ColumnLengthConstrain.LEN_ID_MAX)    private String courseId;        @Column(name = "max_number")    private Integer maxNumber;        @ManyToOne    @JoinColumn(name = "course_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)    private CourseEntity courseByCourseId;}
@Datapublic class CustomerCourseEntityPK implements Serializable {    private static final long serialVersionUID = 1L;    private String customerId;    private String courseId;}

@EmbeddedId:联合主键

标注在实体类成员变量或 getter 方法上。

功能与 @IdClass 一样用于指定联合主键。不同的是其标注在实体内的主键类变量上,且主键类应该标注 @Embeddable 注解。

此外在主键类内指定的字段在实体类内可以不再指定,若再指定则需为 @Column 加上 insertable = false, updatable = false 属性

示例:

@Data@Entity@Table(name = "customer_course")@IdClass(CustomerCourseEntityPK.class)// 指定联合主键类public class CustomerCourseEntity {        @EmbeddedId    private CustomerCourseEntityPK id;        @Column(name = "max_number")    private Integer maxNumber;}
@Data@Embeddablepublic class CustomerCourseEntityPK implements Serializable {    private static final long serialVersionUID = 1L;        @Column(name = "customer_id", length = ColumnLengthConstrain.LEN_ID_MAX)    private String customerId;        @Column(name = "course_id", length = ColumnLengthConstrain.LEN_ID_MAX)    private String courseId;}

@Inheritance:表结构复用

标注在实体类上。

用于表结构复用。指定被该注解修饰的类被子类继承后子类和父类的表结构的关系。

通过 strategy 属性指定关系,有三种策略:


@Inheritance 与 @MappedSuperclass 的区别:


@Inheritance、@MappedSuperClass 可用于定义 Inheritance 关系。这些方式的一个缺点是子类中无法覆盖从父类继承的字段的定义(如父类中 name 是 not null,但子类中允许为 null)。

除了 @Inheritance、@MappedSuperClass 外,还有一种 Inheritance 方法(此法可解决上述不足):先定义一个 Java POJO(干净的 POJO,没有任何对该类使用任何的 ORM 注解),然后不同子类继承该父类,并分别在不同子类中进行 ORM 定义即可。此法下不同子类拥有父类的公共字段且该字段在不同子类中对应的数据库列定义可不同。


@Embedded、@Embeddable

当一个实体类要在多个不同的实体类中进行使用,而其不需要生成数据库表


@Enumerated:映射枚举

使用此注解映射枚举字段,以String类型存入数据库

注入数据库的类型有两种:EnumType.ORDINAL(Interger)、EnumType.STRING(String)


@TableGenerator:主键值生成器

TableGenerator定义一个主键值生成器,在 @GeneratedValue的属性strategy = GenerationType.TABLE时,generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。

生成器是为多个实体类提供连续的ID值的表,每一行为一个类提供ID值,ID值通常是整数。

属性说明:

示例:

@Entitypublic class Employee {    @Id    @Column(name = "id")    @TableGenerator(name = "hf_opert_id_gen", // 此处的名字要和下面generator属性值一致    table = "mcs_hibernate_seq",// 主键保存到数据库的表名    pkColumnName = "sequence_name", // 表里用来保存主键名字的字段    valueColumnName = "sequence_next_hi_value",// 表里用来保存主键值的字段    pkColumnValue = "user_id", // 表里名字字段对应的值    allocationSize = 1)// 自动增长,设置为1    @GeneratedValue(strategy = GenerationType.TABLE, generator = "hf_opert_id_gen")    private Integer id;}

@JoinColumn、@JoinColumns

@JoinColumn:指定外键

如果在实体类的某个属性上定义了联表关系(OneToOne或OneTOMany等),则使用@JoinColumn注解来定义关系的属性。JoinColumn的大部分属性和Column类似。

属性说明:

@Data@Entitypublic class Person {    ...        // Person和Address是一对一关系。Address表中名为id_address的列作为外键指向Person表中名为address_id的列    @OneToOne    @JoinColumn(name="address_id", referencedColumnName="id_address", unique=true)    private Address address;}@Data@Entitypublic class Address {        @Id    @column(name ="id_address")    private Integer idAddress;}

@JoinColumns

如果在实体类的某个属性上定义了联表关系(OneToOne或OneTOMany等),并且关系存在多个JoinColumn,则使用@JoinColumns注解定义多个JoinColumn的属性。

属性说明:

@Data@Entitypublic class Custom {        // Custom和Order是一对一关系。Order表中一个名为CUST_ID的列作为外键指向Custom对应表中名为ID_CUST的列,另一名为CUST_NAME的列作为外键指向Custom对应表中名为NAME_CUST的列    @OneToOne    @JoinColumns({        @JoinColumn(name="CUST_ID", referencedColumnName="ID_CUST"),        @JoinColumn(name="CUST_NAME", referencedColumnName="NAME_CUST")    })    private Order order;}

@OneToOne、@OneToMany

@OneToOne

描述一个 一对一的关联

属性说明:

@Data@Entitypublic class Person {    ...        // Person和Address是一对一关系。Address表中名为id_address的列作为外键指向Person表中名为address_id的列    @OneToOne    @JoinColumn(name="address_id", referencedColumnName="id_address", unique=true)    private Address address;}

@OneToMany

描述一个 一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段。

属性说明:

例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除


@ManyToOne、@ManyToMany

@ManyToOne

表示一个多对一的映射,该注解标注的属性通常是数据库表的外键

属性说明:


@ManyToMany

描述一个多对多的关联。多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理

属性说明:

两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性, 需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称,利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联


@NamedStoredProcedureQuery

定义在一个实体上面声明存储过程。有多个存储过程,可以用@NamedStoredProcedureQueries。


@JsonFormat、@DateTimeFormat

@JsonFormat

后端到前端的时间格式的转换。注意:该注解并非 JPA 注解。

// 出参时间格式化@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date createTime;

也可以在配置文件中配置进行时间戳统一转换:

spring.jackson.date-format=yyyy-MM-dd HH:mm:ssspring.jackson.time-zone=GMT+8

@DateTimeFormat

前端到后端的时间格式的转换。注意:该注解并非 JPA 注解。

// 入参出参时间格式化。请求报文只需要传入"yyyy-MM-dd HH:mm:ss"格式字符串进来,则自动转换为Date类型数据@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")private Date createTime;

主键生成策略

通用策略

@GeneratedValue 注解介绍

参考:JPA注解之“@GeneratedValue”详解

源码定义:

@Target({METHOD,FIELD})    @Retention(RUNTIME)    public @interface GeneratedValue{        GenerationType strategy() default AUTO;        String generator() default "";    } 

其中GenerationType:

public enum GenerationType{        TABLE,        SEQUENCE,        IDENTITY,        AUTO   }  

JPA 提供的四种标准用法为:


AUTO、IDENTITY、SEQUENCE 策略

TABLE 策略


hibernate 策略

hibernate 提供多种主键生成策略,有点是类似于 JPA,基于 Annotation 的方式通过 @GenericGenerator 注解实现。

@GenericGenerator 注解介绍

源码定义:

@Target({PACKAGE, TYPE, METHOD, FIELD})  @Retention(RUNTIME)  public @interface GenericGenerator {   String name();   String strategy();   Parameter[] parameters() default {};  } 

以上属性说明如下:


hibernate 特有策略

使用示例:

// uuid@GeneratedValue(generator = "paymentableGenerator")    @GenericGenerator(name = "paymentableGenerator", strategy = "uuid")// 除以下所列特殊适配格式外,其他策略均采用上面第一种格式// select@GeneratedValue(generator = "paymentableGenerator")  @GenericGenerator(name="select", strategy="select",                    parameters = { @Parameter(name = "key", value = "idstoerung") }) // sequence@GeneratedValue(generator = "paymentableGenerator")  @GenericGenerator(name = "paymentableGenerator", strategy = "sequence",                   parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })  // seqhilo@GeneratedValue(generator = "paymentableGenerator")  @GenericGenerator(name = "paymentableGenerator", strategy = "seqhilo",                    parameters = { @Parameter(name = "max_lo", value = "5") })  // foreign @GeneratedValue(generator = "idGenerator")  @GenericGenerator(name = "idGenerator", strategy = "foreign",                   parameters = { @Parameter(name = "property", value = "employee") }) // sequence-identity@GeneratedValue(generator = "paymentableGenerator")  @GenericGenerator(name = "paymentableGenerator", strategy = "sequence-identity",                  parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })

对于这些 hibernate 主键生成策略和各自的具体生成器之间的关系,在 org.hibernate.id.IdentifierGeneratorFactory 中指定了:

static {    GENERATORS.put("uuid", UUIDHexGenerator.class);    GENERATORS.put("hilo", TableHiLoGenerator.class);    GENERATORS.put("assigned", Assigned.class);    GENERATORS.put("identity", IdentityGenerator.class);    GENERATORS.put("select", SelectGenerator.class);    GENERATORS.put("sequence", SequenceGenerator.class);    GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);    GENERATORS.put("increment", IncrementGenerator.class);    GENERATORS.put("foreign", ForeignGenerator.class);    GENERATORS.put("guid", GUIDGenerator.class);    GENERATORS.put("uuid.hex", UUIDHexGenerator.class); //uuid.hex is deprecated    GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);  }  // 上面十二种策略,加上native,hibernate一共默认支持十三种生成策略。

自定义策略

hibernate 每种主键生成策略提供接口 org.hibernate.id.IdentifierGenerator 的实现类,如果要实现自定义的主键生成策略也必须实现此接口。

IdentifierGenerator 提供一个 generate 方法,generate 方法返回产生的主键。

// 源码展示public interface IdentifierGenerator {          public static final String ENTITY_NAME = "entity_name";          public Serializable generate(SessionImplementor session, Object object)       throws HibernateException;  }  

自定义主键生成策略


Repository 相关注解

Repository 相关注解主要在 SpringDataJpa 的 Repository 中使用。

来源地址:https://blog.csdn.net/footless_bird/article/details/129242569

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯