JPA常见注解
注解名 | 必选 | 属性描述 |
@Entity | 是 | name属性对应一个表名 |
@Table | 否 | name:可选,表示表的名称.默认地,表名和实体名称一致,只有在不一致的情况下才需要指定表名。 catalog:可选,表示Catalog名称,默认为Catalog("")。 schema:可选,表示Schema名称,默认为Schema("")。 |
@Id | 是 | @id定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键.置于getXxxx()前。 |
@GeneratedValue | 否 | strategy:表示主键生成策略,有AUTO,INDENTITY,SEQUENCE和TABLE4种,分别表示让ORM框架自动选择,根据数据库的Identity字段生成,根据数据库表的Sequence字段生成,以有根据一个额外的表生成主键,默认为AUTO。 generator:表示主键生成器的名称,这个属性通常和ORM框架相关,例如,Hibernate可以指定uuid等主键生成方式. |
@Basic | 否 | @Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认即为@Basic。 fetch: 表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER。 optional:表示该属性是否允许为null,默认为true。 |
@Column | 否 | @Column描述了数据库表中该字段的详细定义,这对于根据JPA注解生成数据库表结构的工具非常有作用。 name:表示数据库表中该字段的名称,默认情形属性名称一致。 nullable:表示该字段是否允许为null,默认为true。 unique:表示该字段是否是唯一标识,默认为false。 length:表示该字段的大小,仅对String类型的字段有效。 insertable:表示在ORM框架执行插入操作时,该字段是否应出现INSETRT语句中,默认为true。 updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true.对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段。 columnDefinition:表示该字段在数据库中的实际类型.通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型,该属性非常有用。 secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。 |
@Transient | 否 | @Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。 如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic。 |
@Lob | 否 | @Lob标示该字段为大文本类型。 |
@SecondaryTable | 否 | 一个entity class可以映射到多表,SecondaryTable用来定义单个从表的名字,主键名字等属性。 元数据属性说明: • name: 表名 • catalog: 对应关系数据库中的catalog • schema:对应关系数据库中的schema • pkJoin: 定义一个PrimaryKeyJoinColumn数组,指定从表的主键列 • UniqueConstraints: 定义一个UniqueConstraint数组,指定需要建唯一约束的列
|
@SecondaryTables | 否 | 包含多个@SecondaryTable |
@UniqueConstraints | 否 | 一般用在@SecondaryTable中 |
@OneToOne | 否 | 一对一的关系 |
@OneToMany | 否 | 一对多的关系 |
@ManyToOne | 否 | 多对一的关系 |
@ManyToMany | 否 | 多对多的关系 |
@JoinColumn | 否 | 如果在entity class的field上定义了关系(one2one或one2many等),我们通过JoinColumn来定义关系的属性。JoinColumn的大部分属性和Column类似。
元数据属性说明: • name:列名。 • referencedColumnName:该列指向列的列名(建表时该列作为外键列指向关系另一端的指定列) • unique: 是否唯一 • nullable: 是否允许为空 • insertable: 是否允许插入 • updatable: 是否允许更新 • columnDefinition: 定义建表时创建此列的DDL • secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。 |
@JoinColumns | 否 | 多个@JoinColumn |
@IdClass | 否 | 用于多个主键的情况 value 属性对应一个Class类, 当entity class使用复合主键时,需要定义一个类作为id class。 id class必须符合以下要求: 类必须声明为public,并提供一个声明为public的空构造函数。 必须实现Serializable接口,覆写 equals() 和 hashCode()方法。 entity class的所有id field在id class都要定义,且类型一样。
如果实体对象必须按照检索实体部分中所示的主键来检索实体对象, 那么就需要ID类。否则可以不使用@IdClass注解,只需要使用多个@Id注解即可 |
@Embeddable | 否 | 注解到类上,表示可以嵌入到其他类 |
@Embedded | 否 | 注解到属性上,表示嵌入其他类到此Entity |
@EmbeddedId | 否 | 复合主键,主键字段是在可嵌入类中定义的。该实体包含一个单独的主键字段,该字段用@EmbeddedId 注释,并包含一个可嵌入类的实例。当使用这个表单时,没有定义一个单独的ID类,因为可嵌入的类本身可以表示完整的主键值。 |
@MapKey | 否 | 当存在一个一对一或者一对多的关系时,采用Map来保存。默认用主键值做key,如果使用复合主键,则用id class的实例做key,如果指定了name属性,就用指定的field的值做key。 |
@OrderBy | 否 | 在一对多,多对多关系中,有时我们希望从数据库加载出来的集合对象是按一定方式排序的, 这可以通过OrderBy来实现,默认是按对象的主键升序排列。 元数据属性说明: • value: 字符串类型,指定排序方式。 格式为”fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],……”,排序类型可以不指定,默认是ASC。 |
@PrimaryKeyJoinColumn | 否 | 在三种情况下会用到PrimaryKeyJoinColumn。 • 继承。 • entity class映射到一个或多个从表。从表根据主表的主键列(列名为referencedColumnName值的列),建立一个类型一样的主键列,列名由name属性定义。 • one2one关系,关系维护端的主键作为外键指向关系被维护端的主键,不再新建一个外键列。
元数据属性说明: • name:列名。 • referencedColumnName:该列引用列的列名 • columnDefinition: 定义建表时创建此列的DDL |
@PrimaryKeyJoinColumns | 否 | 用于复合主键情况下的PrimaryKeyJoinColumn |
@Version | 否 | 加入乐观锁 |
@DynamicInsert | 否 | 插入时忽略null |
@DynamicUpdate | 否 | 更新时忽略null |
hibernate注解
注解名 | 必选 | 属性描述 |
@Temporal | 否 | 当我们使用到java.util包中的时间日期类型,则需要此注释来说明转化成java.util包中的类型。 注入数据库的类型有三种: TemporalType.DATE(2008-08-08) TemporalType.TIME(20:00:00) TemporalType.TIMESTAMP(2008-08-08 20:00:00.000000001) |
@Enumerated | 否 | 使用此注解映射枚举字段,以String类型存入数据库 注入数据库的类型有两种:EnumType.ORDINAL(Interger)、EnumType.STRING(String) |
@ElementCollection | 否 | 集合映射 |
@CreatedDate | 否 | 创建时间字段(insert自动设置) 用法:下同 2、@EnableJpaAuditing:在启动类中加此注解 3、在实体类中属性中加上面四种注解 4、自定义添加用户 |
@CreatedBy | 否 | 创建用户字段(insert自动设置) |
@LastModifiedDate | 否 | 最后修改时间字段(update自定设置) |
@LastModifiedBy | 否 | 最后修改用户字段(update自定设置) |
@AttributeOverride | 否 | 一般配合@Embedded或者@MappedSuperclass使用,对属性进行重新映射 |
@AttributeOverrides | 否 | 多个@AttributeOverride的情况 |
@MappedSuperclass | 否 | 1.标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。 2.标注为@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口。
|
@EntityGraph | 否 | 解决N+1的问题 |
@NamedEntityGraph | 否 |
|
Hibernate验证注解
注解名 | 适用类型 | 示例 |
@Pattern | String | 通过正则表达式来验证字符串 @attern(regex=”[a-z]{6}”) |
@Length | String | 验证字符串的长度 @length(min=3,max=20) |
String | 验证一个Email地址是否有效 @email | |
@Range | 数值 | 验证一个整型是否在有效的范围内 @Range(min=0,max=100) |
@Min | 数值 | 验证一个整型必须不小于指定值 @Min(value=10) |
@Max | 数值 | 验证一个整型必须不大于指定值 @Max(value=20) |
@Size | 集合或数组 | 集合或数组的大小是否在指定范围内 @Size(min=1,max=255) |
@NotNull | 任意 | 值不能为空 |
@Null | 任意 | 值必须为空 |
@NotBlank | String | 字符串不能为空格 |
@NotEmpty | String,集合 | 字符串不能空null,集合必须有值 |
@SafeHtml | String | 字符串必须是安全的html |
@URL | String | 字符串必须是合法的URL |
@AssertTrue |
| 判断元素必须为 true |
@AssertFalse |
| 判断元素必须为 |
@DecimalMin | 数值 | 断数值元素大于等于指定的最小值 |
@DecimalMax | 数值 | 断数值元素小于等于指定的最大值 |
@Past | 日期 | 判断日期元素必须是一个过去的日期 |
@Future | 日期 | 判断日期元素必须是一个将来的日期 |
@Valid | 集合或对象 | 该注解主要用于字段为一个包含其他对象的集合或map或数组的字段,或该字段直接为一个其他对象的引用,这样在检查当前对象的同时也会检查该字段所引用的对象。 |
@Digits | 小数 | 验证注解的元素值的整数位数和小数位数上限 |
以上每个注解都可能性有一个message属性,用于在验证失败后向用户返回的消息
注解区别
一、@OneToMany与@ManyToOne的区别
二、@MapsId与@JoinColumn
@MapsId与@JoinColumn在表只有一个外键时,没有任何区别,但是在表有多个相同的外键时,便只能使用@JoinColumn。
例如:EmailTable有sendId与receiveId两个指向UserTable的外键
三、@JoinTable与@JoinColumn
@JoinColumn标识本表中指向另外一个表中的外键
@JoinTable用于多对多关系中,指定中间表
四、Domain服务划分时,@Embedded与@OneToMany或ManyToOne的区别
五、CascadeType属性区别
场景:Book与BookDetail
CascadeType.PERSIST —-级联保存
- 当Book实体拥有的BookDetail在数据库中不存在时,保存Book的同时也会保存BookDetail
CascadeType.MERGE —-级联更新
- 当Student中的数据改变,会相应地更新Course中的数据。
CascadeType.REMOVE —-级联删除
- 删除当前实体时,与它有映射关系的实体也会跟着被删除。
CascadeType.REFRESH —-级联刷新
- 假设场景 有一个订单,订单里面关联了许多商品,这个订单可以被很多人操作,那么这个时候A对此订单和关联的商品进行了修改,与此同时,B也进行了相同的操作,但是B先一步比A保存了数据,那么当A保存数据的时候,就需要先刷新订单信息及关联的商品信息后,再将订单及商品保存。
CascadeType.DETACH ——级联脱管/游离操作。
- 如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联。
CascadeType.ALL —-级联所有
- 拥有以上所有级联操作权限。
六、FetchType属性区别
- FetchType.LAZY
懒加载,在访问关联对象的时候加载(即从数据库读入内存)
在session未关闭前循环List,显示调用,举例如下
for(B b : b.List){
b.getA();
}
- FetchType.EAGER
立刻加载,在查询主对象的时候同时加载关联对象。
七、FetchType与FetchMode的区别
两者都是设定关联对象的加载策略。前者是JPA标准的通用加载策略注解属性,
后者是Hibernate自有加载策略注解属性。
FetchMode可选值意义与区别如下:
@Fetch(FetchMode.JOIN): 始终立刻加载,使用外连(outer join)查询的同时加载关联对象,忽略FetchType.LAZY设定。
@Fetch(FetchMode.SELECT) :默认懒加载(除非设定关联属性lazy=false),当访问每一个关联对象时加载该对象,会累计产生N+1条sql语句
@Fetch(FetchMode.SUBSELECT) 默认懒加载(除非设定关联属性lazy=false),在访问第一个关联对象时加载所有的关联对象。会累计产生两条sql语句。且FetchType设定有效。
八、OrphanRemoval —-去掉孤值
如果OrphanRemoval等于true,则在删除存在级联关系的对象时。
没有设置 CascadeType.all 或者 remove,否则只会更新关联字段为null。
//单向一对多,user里有addresses
public class User{
//@OneToMany(orphanRemoval = true)//此时移除user里的某一个address会级联更新该userId字段为null
//@OneToMany(orphanRemoval = false)//此时移除user里的某一个address会级联更新该userId字段为null
//@OneToMany(cascade=CascadeType.ALL,orphanRemoval = true)//此时移除user里的某一个address会级联删除该address
//@OneToMany(cascade=CascadeType.ALL,orphanRemoval = false)//此时移除user里的某一个address会级联更新该userId字段为null
@JoinColumn(name="userId")
private Set<Address> addresses;
//...
}
//address里没有user
public class Address{
//...
}
//双向一对多的一端,user里有addresses
public class User{
//@OneToMany(orphanRemoval = true,mappedBy="user",)//此时移除user里的某一个address无任何效果
//@OneToMany(orphanRemoval = false,mappedBy="user",)//此时移除user里的某一个address无任何效果
//@OneToMany(cascade=CascadeType.ALL,orphanRemoval = true,mappedBy="user",)//此时移除user里的某一个address会级联删除该address
//@OneToMany(cascade=CascadeType.ALL,orphanRemoval = false,mappedBy="user",)//此时移除user里的某一个address无任何效果
//注解mappedBy表示自己不维护关系,由Address来维护关系
private Set<Address> addresses;
//...
}
//双向一对多的多端,address里有user
public class Address{
@ManyToOne
@JoinColumn(name="userId")
private User user;
//...
}
九、JPA的两种删除
1. Explicit Remove 明确的删除 调用remove方法删除
2. Cascading Remove (or All) 级联删除 OrphanRemoval =true 级联删除方式
九、optional属性
optional属性是定义该关联类是否必须存在,值为false 时,关联类双方都必须存在,如果关系被维护端不存在,查询的结果为null。值为true 时, 关系被维护端可以不存在,查询的结果仍然会返回关系维护端,在关系维护端中指向关系被维护端的属性为null。optional属性的默认值是true。optional 属性实际上指定关联类与被关联类的join 查询关系,如optional=false 时join 查询关系为inner join, optional=true 时join 查询关系为left join。
十、JPA查询
十一、JPA存储
@Column(name = "card_list", columnDefinition = "json")
@Convert(converter = CardListConverter.class)
private CardListVO cardList;
public class CardListConverter implements AttributeConverter<CardListVO, String> {
@Override
public String convertToDatabaseColumn(CardListVO attribute) {
return JSON.toJSONString(attribute);
}
@Override
public CardListVO convertToEntityAttribute(String dbData) {
if (StringUtils.isEmpty(dbData)) {
return new CardListVO();
}
return JSON.parseObject(dbData, CardListVO.class);
}
}