1. 基本注解
1.1 @Entity
由 @Entity
定義的對(duì)象會(huì)成為被 JPA 管理的實(shí)體超陆,將映射到指定的數(shù)據(jù)庫(kù)表中庇勃。
public @interface Entity {
//可選,默認(rèn)是此實(shí)體類(lèi)名攒驰,全局唯一
String name() default "";
}
1.2 @Table
用于指定數(shù)據(jù)庫(kù)的表名头岔。
public @interface Table {
//表的名字,如果不寫(xiě),則默認(rèn)與實(shí)體的名字一樣
String name() default "";
//此表的catalog
String catalog() default "";
//此表的schema
String schema() default "";
//唯一性約束延欠,只有創(chuàng)建表的時(shí)候用,默認(rèn)不需要
UniqueConstraint[] uniqueConstraints() default {};
//索引沈跨,只有創(chuàng)建表的時(shí)候使用由捎,默認(rèn)不需要
Index[] indexes() default {};
}
1.3 @Id
定義數(shù)據(jù)庫(kù)的主鍵,一個(gè)實(shí)體里至少有一個(gè)主鍵饿凛。
1.4 @IdClass
聯(lián)合主鍵狞玛。
public @interface IdClass {
//聯(lián)合主鍵的類(lèi)
Class value();
}
聯(lián)合主鍵的用處就是一個(gè)表中能存在多個(gè)主鍵,這些主鍵在關(guān)聯(lián)在外部的一個(gè)對(duì)象中涧窒,這個(gè)對(duì)象需要滿(mǎn)足以下條件
- 必須實(shí)現(xiàn)
Serializable
接口 - 必須有默認(rèn)的
public
無(wú)參構(gòu)造方法 - 必須覆蓋
equals()
和hashCode()
方法
1.5 @GeneratedValue
主鍵生成策略心肪。
public @interface GeneratedValue {
//Id生成策略,默認(rèn)GenerationType.AUTO
GenerationType strategy() default GenerationType.AUTO;
//通過(guò)Sequences生成Id纠吴,常見(jiàn)的是Orcale數(shù)據(jù)庫(kù)的Id生成規(guī)則硬鞍,需要配合@SequenceGenerator使用
String generator() default "";
}
public enum GenerationType {
//通過(guò)表產(chǎn)生主鍵,框架由表模擬序列產(chǎn)生主鍵戴已,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫(kù)移植
TABLE,
//通過(guò)序列產(chǎn)生主鍵固该,通過(guò)@SequenceGenerator注解指定序列名,Mysql不支持這種方式
SEQUENCE,
//采用數(shù)據(jù)庫(kù)Id自增恭陡,用于Mysql數(shù)據(jù)庫(kù)
IDENTITY,
//JPA默認(rèn)選項(xiàng)蹬音,自動(dòng)選擇策略
AUTO;
private GenerationType() {
}
}
1.6 @Basic
@Basic
表示屬性是到數(shù)據(jù)庫(kù)的字段的映射,如果實(shí)體的字段上沒(méi)有任何注解休玩,默認(rèn)為 @Basic
著淆。
public @interface Basic {
//EAGER是立即加載,這是默認(rèn)方式拴疤,可以看到還有一種LAZY懶加載
FetchType fetch() default FetchType.EAGER;
//Optional 類(lèi)是一個(gè)可以為null的容器對(duì)象永部,設(shè)置為true,則表示字段可以為null呐矾,默認(rèn)可以
boolean optional() default true;
}
public enum FetchType {
LAZY,
EAGER;
private FetchType() {
}
}
1.7 @Transient
@Transient
表示該屬性并非一個(gè)到數(shù)據(jù)庫(kù)表的字段的映射苔埋,是非持久化屬性,與 @Basic
作用相反蜒犯。
實(shí)體中有數(shù)據(jù)庫(kù)中不存在的字段组橄,可以加上 @Transient
注解,忽略這個(gè)字段的映射罚随。
1.8 @Column
public @interface Column {
String name() default "";
//表示該字段是否為唯一標(biāo)識(shí)玉工,默認(rèn)為false,如果表中有一個(gè)字段需要唯一標(biāo)識(shí)淘菩,則既可以使用該標(biāo)記遵班,也可以使用@Table標(biāo)記中的@UniqueConstraint
boolean unique() default false;
//數(shù)據(jù)字段是否允許為空,默認(rèn)允許
boolean nullable() default true;
//執(zhí)行insert操作時(shí)是否包含此字段,默認(rèn)包含
boolean insertable() default true;
//執(zhí)行update操作時(shí)是否包含此字段狭郑,默認(rèn)包含
//insertable和updatable屬性一般多用于只讀的屬性腹暖,例如主鍵和外鍵等。這些字段的值通常是自動(dòng)生成的
boolean updatable() default true;
//表示創(chuàng)建表時(shí)翰萨,該字段創(chuàng)建的SQL語(yǔ)句脏答,一般用于通過(guò)Entity生成表定義時(shí)使用
String columnDefinition() default "";
//表示當(dāng)映射多個(gè)表時(shí),指定表的表中的字段亩鬼。默認(rèn)值為主表的表名
String table() default "";
//字段長(zhǎng)度以蕴,默認(rèn)255
int length() default 255;
// precision 屬性和 scale 屬性表示精度,當(dāng)字段類(lèi)型為double時(shí)辛孵,precision表示數(shù)值的總長(zhǎng)度,scale表示小數(shù)點(diǎn)所占的位數(shù)
int precision() default 0;
int scale() default 0;
}
1.9 @Temporal
@Temporal
用來(lái)設(shè)置 Date 類(lèi)型的屬性映射到對(duì)應(yīng)精度的字段赡磅,也就是對(duì)日期進(jìn)行格式化魄缚。
public enum TemporalType {
DATE,
TIME,
TIMESTAMP;
private TemporalType() {
}
}
public @interface Temporal {
TemporalType value();
}
public enum TemporalType {
DATE,
TIME,
TIMESTAMP;
private TemporalType() {
}
}
可以看到有三種格式化方式,
-
@Temporal(TemporalType.DATE)
: 實(shí)體類(lèi)會(huì)封裝成日期yyyy-MM-dd
的 Date 類(lèi)型焚廊。 -
@Temporal(TemporalType.TIME)
: 實(shí)體類(lèi)會(huì)封裝成時(shí)間hh-MM-ss
的 Date 類(lèi)型冶匹。 -
@Temporal(TemporalType.TIMESTAMP)
: 實(shí)體類(lèi)會(huì)封裝成完整的時(shí)間yyyy-MM-dd hh:MM:ss
的 Date 類(lèi)型。
1.10 @Enumerated
用于直接映射枚舉類(lèi)型的字段咆瘟。
public @interface Enumerated {
EnumType value() default EnumType.ORDINAL;
}
1.11 @Lob
@Lob
將屬性映射為數(shù)據(jù)庫(kù)支持的大對(duì)象類(lèi)型嚼隘,支持以下兩種數(shù)據(jù)庫(kù)類(lèi)型的字段。
-
Clob
:長(zhǎng)字符串類(lèi)型袒餐,java.sql.Clob
飞蛹、Character[]
、char[]
灸眼、String
都將被映射成Clob
類(lèi)型卧檐。 -
Blob
:字節(jié)類(lèi)型,java.sql.Blob
焰宣、Byte[]
霉囚、byte[]
、實(shí)現(xiàn)了 Serializable 接口類(lèi)型都將被映射成Blob
類(lèi)型匕积。
2. JPA 中的實(shí)體關(guān)系
簡(jiǎn)單地用原始字段持久化一個(gè)對(duì)象只是等式的一半盈罐。JPA 還具有管理彼此相關(guān)的實(shí)體的能力。表和對(duì)象中都可能存在四種實(shí)體關(guān)系:
- 一對(duì)多
- 多對(duì)一
- 多對(duì)多
- 一對(duì)一
2.1 @JoinColumn
定義外鍵關(guān)聯(lián)的字段名稱(chēng)闪唆。
public @interface JoinColumn {
//注解所在當(dāng)前表的主鍵名盅粪,必須寫(xiě)
String name() default "";
//關(guān)聯(lián)外部表的列名,默認(rèn)是外部主鍵名
String referencedColumnName() default "";
//外鍵字段是否唯一
boolean unique() default false;
//外鍵字段是否允許為空
boolean nullable() default true;
//是否跟隨一起新增
boolean insertable() default true;
//是否跟隨一起更新
boolean updatable() default true;
String columnDefinition() default "";
String table() default "";
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
配合 @OneToOne
苞氮、@OneToMany
湾揽、@ManyToOne
一起使用。
2.2 關(guān)系映射注解
public @interface OneToOne {
//關(guān)系目標(biāo)實(shí)體,默認(rèn)為該字段的類(lèi)型
Class targetEntity() default void.class;
//級(jí)聯(lián)操作策略
CascadeType[] cascade() default {};
//數(shù)據(jù)獲取方式库物,立即加載和延遲加載
FetchType fetch() default FetchType.EAGER;
boolean optional() default true;
//關(guān)聯(lián)關(guān)系被誰(shuí)維護(hù)霸旗,一般不需要特別指定, 只有關(guān)系維護(hù)方才能操作兩者的關(guān)系,被維護(hù)方即使設(shè)置了維護(hù)方屬性進(jìn)行存儲(chǔ)也不會(huì)更新外鍵關(guān)聯(lián)
//mappedBy不能與@JoinColumn或者@JoinTable同時(shí)使用
//mappedBy的值是指另一方的實(shí)體里屬性的字段戚揭,而不是數(shù)據(jù)庫(kù)字段诱告,也不是實(shí)體的對(duì)象的名字,是另一方配置了@JoinColumn或者@JoinTable注解的屬性的字段名稱(chēng)
String mappedBy() default "";
//是否級(jí)聯(lián)刪除民晒,和 CascadeType.REMOVE 的效果一樣精居,只是配置了兩種中的一種就會(huì)自動(dòng)級(jí)聯(lián)刪除
boolean orphanRemoval() default false;
}
public enum CascadeType {
ALL,
PERSIST,
MERGE,
REMOVE,
REFRESH
}
級(jí)聯(lián)操作策略代碼舉例解釋
public class Student {
@ManyToMany(cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
private Set<Course> courses = new HashSet<>();
}
- CascadeType.PERSIST 級(jí)聯(lián)新建:若 Student 實(shí)體持有的 Course 實(shí)體在數(shù)據(jù)庫(kù)中不存在時(shí),Student 保存時(shí)自動(dòng)在 Course 實(shí)體對(duì)應(yīng)的數(shù)據(jù)庫(kù)中保存 Course 數(shù)據(jù)潜必。
- CascadeType.MERGE 級(jí)聯(lián)更新:當(dāng) Student 中的數(shù)據(jù)改變靴姿,會(huì)相應(yīng)地更新 Course 中的數(shù)據(jù)。
- CascadeType.REMOVE 級(jí)聯(lián)刪除:刪除 Student 實(shí)體磁滚,與它有映射關(guān)系的 Course 實(shí)體也會(huì)跟著被刪除佛吓。
- CascadeType.REFRESH 級(jí)聯(lián)刷新:Student 保存時(shí)重新加載 Course 關(guān)系
- CascadeType.DETACH 級(jí)聯(lián)脫離:要?jiǎng)h除一個(gè)實(shí)體,直接撤銷(xiāo)所有相關(guān)的外鍵關(guān)聯(lián)
- CascadeType.ALL 擁有以上所有級(jí)聯(lián)操作權(quán)限
- 默認(rèn)垂攘,關(guān)系表不會(huì)產(chǎn)生任何影響
@OneToOne
需要配合 @JoinColumn 一起使用
在使用@OneToOne
進(jìn)行雙向關(guān)聯(lián)時(shí)维雇,需要在類(lèi)上加上注解 @JsonIdentityInfo
,這個(gè)注解被用來(lái)在序列化/反序列化時(shí)為該對(duì)象或字段添加一個(gè)對(duì)象識(shí)別碼晒他,通常是用來(lái)解決循環(huán)嵌套的問(wèn)題吱型。通過(guò)配置屬性 generator 來(lái)確定識(shí)別碼生成的方式,配置屬性 property 來(lái)確定識(shí)別碼的名稱(chēng)陨仅,識(shí)別碼名稱(chēng)沒(méi)有限制津滞。
一般這個(gè)注解可以這么加
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
@OneToMany
和 @ManyToOne
同上。
2.3 @OrderBy
用于關(guān)聯(lián)查詢(xún)時(shí)排序掂名。
@Entity
public class Course {
...
@ManyToMany
@OrderBy("lastname ASC")
public List getStudents() {...};
...
}
@Entity
public class Student {
...
@ManyToMany(mappedBy="students")
@OrderBy //默認(rèn)使用主鍵排序
public List getCourses() {...};
...
}
3. 查詢(xún)
注意: 這里是接口据沈,是
persistence-api
包中的,項(xiàng)目里Repository
里的接口上面實(shí)現(xiàn)的@Query
注解不是下面這個(gè)饺蔑,spring-data-jpa
的查詢(xún)和解析留待下回分解
/**
* Interface used to control query execution.
*
* @since Java Persistence 1.0
*/
public interface Query {
/**
* Execute a SELECT query and return the query results
* as a List.
* @return a list of the results
* @throws IllegalStateException if called for a Java
* Persistence query language UPDATE or DELETE statement
*/
public List getResultList();
/**
* Execute a SELECT query that returns a single result.
* @return the result
* @throws NoResultException if there is no result
* @throws NonUniqueResultException if more than one result
* @throws IllegalStateException if called for a Java
* Persistence query language UPDATE or DELETE statement
*/
public Object getSingleResult();
/**
* Execute an update or delete statement.
* @return the number of entities updated or deleted
* @throws IllegalStateException if called for a Java
* Persistence query language SELECT statement
* @throws TransactionRequiredException if there is
* no transaction
*/
public int executeUpdate();
/**
* Set the maximum number of results to retrieve.
* @param maxResult
* @return the same query instance
* @throws IllegalArgumentException if argument is negative
*/
public Query setMaxResults(int maxResult);
/**
* Set the position of the first result to retrieve.
* @param startPosition the start position of the first result, numbered from 0
* @return the same query instance
* @throws IllegalArgumentException if argument is negative
*/
public Query setFirstResult(int startPosition);
/**
* Set an implementation-specific hint.
* If the hint name is not recognized, it is silently ignored.
* @param hintName
* @param value
* @return the same query instance
* @throws IllegalArgumentException if the second argument is not
* valid for the implementation
*/
public Query setHint(String hintName, Object value);
/**
* Bind an argument to a named parameter.
* @param name the parameter name
* @param value
* @return the same query instance
* @throws IllegalArgumentException if parameter name does not
* correspond to parameter in query string
* or argument is of incorrect type
*/
public Query setParameter(String name, Object value);
/**
* Bind an instance of java.util.Date to a named parameter.
* @param name
* @param value
* @param temporalType
* @return the same query instance
* @throws IllegalArgumentException if parameter name does not
* correspond to parameter in query string
*/
public Query setParameter(String name, Date value, TemporalType temporalType);
/**
* Bind an instance of java.util.Calendar to a named parameter.
* @param name
* @param value
* @param temporalType
* @return the same query instance
* @throws IllegalArgumentException if parameter name does not
* correspond to parameter in query string
*/
public Query setParameter(String name, Calendar value, TemporalType temporalType);
/**
* Bind an argument to a positional parameter.
* @param position
* @param value
* @return the same query instance
* @throws IllegalArgumentException if position does not
* correspond to positional parameter of query
* or argument is of incorrect type
*/
public Query setParameter(int position, Object value);
/**
* Bind an instance of java.util.Date to a positional parameter.
* @param position
* @param value
* @param temporalType
* @return the same query instance
* @throws IllegalArgumentException if position does not
* correspond to positional parameter of query
*/
public Query setParameter(int position, Date value, TemporalType temporalType);
/**
* Bind an instance of java.util.Calendar to a positional parameter.
* @param position
* @param value
* @param temporalType
* @return the same query instance
* @throws IllegalArgumentException if position does not
* correspond to positional parameter of query
*/
public Query setParameter(int position, Calendar value, TemporalType temporalType);
/**
* Set the flush mode type to be used for the query execution.
* The flush mode type applies to the query regardless of the
* flush mode type in use for the entity manager.
* @param flushMode
*/
public Query setFlushMode(FlushModeType flushMode);
}