参考文档:JPA 概述及常用注解详解、SpringDataJpa 使用指南-阿里云开发者社区 (aliyun.com)
概述
JPA(Java Persistence API)是 Java 标准中的一套ORM规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现,如Hiernate、TopLink 、Eclipselink等都是 JPA 的具体实现),借助 JPA 技术可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中(即Object Model与Data Model间的映射)。
JPA是Java持久层API,由Sun公司开发,希望规范、简化 Java 对象的持久化工作,整合ORM 技术,整合第三方 ORM 框架,建立一种标准的方式,目前也是在按照这个方向发展,但是还没能完全实现。在ORM框架中,Hibernate框架做了较好的 JPA 实现,已获得 Sun 的兼容认证。
JPA 的优势:
1.开发者面向 JPA 规范的接口,但底层的JPA实现可以任意切换:觉得Hibernate好的,可以选择Hibernate JPA实现;觉得TopLink好的,可以选择TopLink JPA实现。
2.开发者可以避免为使用 Hibernate 学习一套 ORM 框架,为使用 TopLink 又要再学习一套ORM 框架。
JPA为我们提供了以下规范:
- ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中
- JPA的 Criteria API:提供 API 来操作实体对象,执行 CRUD 操作,框架会自动将之转换为对应的 SQL,使开发者从繁琐的 JDBC、SQL中解放出来。
- JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
JPA 注解
实体对象持久化到数据库的示例代码:
@Data
@Entity
@Table(name = "t_business_order",
//建立索引
indexes = {@Index(name="orderId",columnList="orderId",unique=true),
@Index(name="businessId",columnList="businessId",unique=false),
@Index(name="goodsId",columnList="goodsId",unique=false),
@Index(name="deviceId",columnList="deviceId",unique=false)}
)
public class TBusinessOrder {
//用户编号
@Id
//自增
@GeneratedValue(strategy= GenerationType.IDENTITY)
//长整型
@Column(name="id",nullable=false,columnDefinition="BIGINT comment '自增'" )
private Long id;
@Column(name="orderId",nullable=false,unique = true,columnDefinition="VARCHAR(255) comment '订单编号' ")
private String orderId;
@Column(name="businessId",nullable=true,columnDefinition="VARCHAR(255) comment '企业编号' ")
private String businessId;
@Column(name="goodsId",nullable=true,columnDefinition="VARCHAR(255) comment '商品编号' ")
private String goodsId;
@Column(name="deviceId",nullable=true,columnDefinition="VARCHAR(255) comment '设备编号' ")
private String deviceId;
@Column(name="number",nullable=true,columnDefinition="INT comment '商品数量' ")
private Integer number;
@Column(name="price",nullable=true,columnDefinition="DECIMAL(10,2) comment '订单金额' ")
private BigDecimal price;
@Column(name="refundPrice",nullable=true,columnDefinition="DECIMAL(10,2) comment '退款金额' ")
}
Entity 常用注解
指定对象与数据库字段映射时注解的位置:如@Id、@Column等注解指定Entity的字段与数据库字段对应关系时,注解的位置可以在Field(属性)或Property(属性的get方法上),两者统一用其中一种,不能两者均有。推荐用前者。
@Entity、@Table
@Entity(必需)
标注在实体类上。
映射实体类。指出该 Java 类为实体类,将映射到指定的关系数据库表。
应用了此注解后,将会自动将类名映射作为数据库表名、将类内的字段名映射为数据库表的列名。映射策略默认是按驼峰命名法拆分将类名或字段名拆分成多部分,然后以下划线连接,如StudentEntity -> student_entity、studentName -> student_name。若不按默认映射,则可通过@Table、@Column指定,见下面。
@Table(可选)
标注在实体类上。
映射数据库表名。当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用
- schema属性:指定数据库名
- name属性:指定表名,不指定时默认按驼峰命名法拆分将类名,并以下划线连接
@Id、@GeneratedValue
@Id(必需)
标注在实体类成员变量或getter方法之上。
映射生成主键。用于声明一个实体类的属性映射为数据库的一个主键列。
若同时指定了下面的 @GeneratedValue 则存储时会自动生成主键值,否则在存入前用户需要手动为实体赋一个主键值。
主键值类型可以是:
- Primitive types:
boolean, byte, short, char, int, long, float, double
- Equivalent wrapper classes from package java.lang:
Byte,Short, Character, Integer, Long, Float, Double
- java.math.BigInteger, java.math.BigDecimal
- java.lang.String
- java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp
- Any enum type
- Reference to an entity object
- composite of several keys above
指定联合主键,有@IdClass、@EmbeddedId两种方法。
@GeneratedValue
@GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。
默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment
- AUTO: JPA自动选择合适的策略,是默认选项
- IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式
- TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
- SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
@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个属性均为可选属性,各属性含义分别如下:
- name:定义了被标注字段在数据库表中所对应字段的名称。
- unique:该字段是否为唯一标识,默认为false。也可以使用@Table标记中的@UniqueConstraint。
- nullable:该字段是否可以为null值,默认为true。
- length:字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符。
- insertable:在使用“INSERT”脚本插入数据时,是否插入该字段的值。默认为true。
- updatable:在使用“UPDATE”脚本插入数据时,是否更新该字段的值。默认为true。
insertable = false 和updatable = false 一般多用于只读的属性,例如主键和外键等。这些字段的值通常是自动生成的。
- columnDefinition:建表时创建该字段的DDL语句,一般用于通过Entity生成表定义时使用。
(如果DB中表已经建好,该属性没有必要使用)
- precision和scale:表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数。
- table:定义了包含当前字段的表名。
@Basic(可选)
表示一个简单的属性到数据表的字段的映射,对于没有任何标注的属性或 getter 方法,默认标注为 @Basic
- fetch 表示属性的读取策略,有 EAGER 和 LAZY 两种,分别为立即加载和延迟加载
- optional 表示该属性是否允许为 null,默认为 true
@Transient:忽略属性
定义暂态属性。表示该属性并非一个到数据库表的字段的映射,ORM 框架将忽略该属性。
如果一个属性并非数据库表的字段映射,就必须将其标识为 @Transient,否则ORM 框架默认为其注解 @Basic,例如工具方法不需要映射。