基本注解
基本注解包括@Entity、@Table、@Id、@IdClass、
@GeneratedValue、@Basic、@Transient、@Column、@Temporal、
@Enumerated、@Lob。
@Entity
Blog示例:
@Entity
@Entity定义对象将会成为被JPA管理的实体,将映射到指定的数
据库表。
@Table
@Table指定数据库的表名。
源码:
@Target(TYPE)
@Retention(RUNTIME)
public @interface Table {
/**
* (Optional) The name of the table.
* <p> Defaults to the entity name.
*/
String name() default "";
/** (Optional) The catalog of the table.
* <p> Defaults to the default catalog.
*/
String catalog() default "";
/** (Optional) The schema of the table.
* <p> Defaults to the default schema for user.
*/
String schema() default "";
/**
* (Optional) Unique constraints that are to be placed on
* the table. These are only used if table generation is in
* effect. These constraints apply in addition to any constraints
* specified by the <code>Column</code> and <code>JoinColumn</code>
* annotations and constraints entailed by primary key mappings.
* <p> Defaults to no additional constraints.
*/
UniqueConstraint[] uniqueConstraints() default {};
/**
* (Optional) Indexes for the table. These are only used if
* table generation is in effect. Note that it is not necessary
* to specify an index for a primary key, as the primary key
* index will be created automatically.
*
* @since 2.1
*/
Index[] indexes() default {};
}
@Id
@Id定义属性为数据库的主键,一个实体里面必须有一个。
@IdClass
@IdClass利用外部类的联合主键。
作为符合主键类,要满足以下几点要求:
必须实现Serializable接口。
必须有默认的public无参数的构造方法。
必须覆盖equals和hashCode方法。equals方法用于判断两个对
象是否相同,EntityManger通过find方法来查找Entity时是根
据equals的返回值来判断的。在本例中,只有对象的name和
email值完全相同或同一个对象时才返回true,否则返回
false。hashCode方法返回当前对象的哈希码,生成的
76hashCode相同的概率越小越好,算法可以进行优化。
@GeneratedValue
@GeneratedValue为主键生成策略,例如:
GenerationType一共有4个值:
TABLE:通过表产生主键,框架由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
SEQUENCE:通过序列产生主键,通过@SequenceGenerator注解指定序列名,MYSQL不支持这种方式,一般用ORACLE
IDENTITY:采用数据库ID自增长,一般用于MYSQL。
AUTO:JPA自动选择合适的策略,默认为该选项。
@Basic
@Basic表示属性是到数据库表的字段的映射。如果实体的字段上
没有任何注解,默认即为@Basic。
@Transient
@Transient表示该属性并非一个到数据库表的字段的映射,表示
非持久化属性,与@Basic作用相反。JPA映射数据库的时候忽略它。
@Column
@Column定义该属性对应数据库中的列名。
@Temporal
@Temporal用来设置Date类型的属性映射到对应精度的字段。
(1)@Temporal(TemporalType.DATE)映射为日期∥date(只有
日期)。
(2)@Temporal(TemporalType.TIME)映射为日期∥time(只有
时间)。
(3)@Temporal(TemporalType.TIMESTAMP)映射为日期∥date
time(日期+时间)。
@Enumerated
@Enumerated,直接映射enum枚举类型的字段。
源码:
@Lob
@Lob 将属性映射成数据库支持的大对象类型,支持以下两种数
据库类型的字段:
(1)Clob(Character Large Ojects)类型是长字符串类型,
java.sql.Clob、Character[]、char[]和String将被映射为Clob类
型。
(2)Blob(Binary Large Objects)类型是字节类型,
java.sql.Blob、Byte[]、byte[]和实现了Serializable接口的类型
将被映射为Blob类型。
(3)Clob、Blob占用内存空间较大,一般配合
@Basic(fetch=FetchType.LAZY)将其设置为延迟加载。
关联关系注解
关联关系注解包括@JoinColumn、@OneToOne、@OneToMany、
@ManyToOne、@ManyToMany、@JoinTable、@OrderBy。
@JoinColumn定义外键关联的字段名称
源码:
@Repeatable(JoinColumns.class)
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinColumn {
String name() default "";
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(PROVIDER_DEFAULT);
用法:@JoinColumn主要配合@OneToOne、@ManyToOne、
@OneToMany一起使用,单独使用没有意义。
@JoinColumns定义多个字段的关联关系。
@OneToOne关联关系
源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.persistence.CascadeType;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.FetchType.EAGER;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
用法:@OneToOne需要配合@JoinColumn一起使用。
注意: 可以双向关联,也可以只配置一方,需要视实际需求而定。
@OneToManyg与@ManyToOne关联关
系
@OneToMany与@ManyToOne可以相对存在,也可只存在一方。
@OneToMany源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.persistence.CascadeType;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.FetchType.LAZY;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
@ManyToOne与OneToMany的源码稍有区别
@ManyToOne源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.persistence.CascadeType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.FetchType.EAGER;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
}
使用必须和@JoinColumn配合使用才有效。
@OrderBy关联查询时排序
一般和@OneToMany一起使用。
源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OrderBy {
String value() default "";
}
用法示例:
@JoinTable关联关系表
如果对象与对象之间有一个关联关系表的时候,就会用到
@JoinTable,一般和@ManyToMany一起使用。
源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.ConstraintMode.PROVIDER_DEFAULT;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinTable {
String name() default "";
String catalog() default "";
String schema() default "";
JoinColumn[] joinColumns() default {};
JoinColumn[] inverseJoinColumns() default {};
ForeignKey foreignKey() default @ForeignKey(PROVIDER_DEFAULT);
ForeignKey inverseForeignKey() default @ForeignKey(PROVIDER_DEFAULT);
UniqueConstraint[] uniqueConstraints() default {};
Index[] indexes() default {};
}
@ManyToMany关联关系
源码:
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.persistence.CascadeType;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.FetchType.LAZY;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
@ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单
向、双向之分。单向双向和注解没有关系,只看实体类之间是否相互
引用。
示例:
关于关系查询的一些坑
(1)所有的注解要么全配置在字段上,要么全配置在get方法
上,不能混用,混用就会启动不起来,但是语法配置没有问题。
(2)所有的关联都是支持单向关联和双向关联的,视具体业务
场景而定。JSON序列化的时候使用双向注解会产生死循环,需要人为
手动转化一次,或者使用@JsonIgnore。
(3)在所有的关联查询中,表一般是不需要建立外键索引的。
@mappedBy的使用需要注意。
(4)级联删除比较危险,建议考虑清楚,或者完全掌握。
(5)不同的关联关系的配置,@JoinClumn里面的name、
referencedColumnName代表的意思是不一样的,很容易弄混,可以根
据打印出来的SQL做调整。
(6)当配置这些关联关系的时候建议大家直接在表上面,把外
键建好,然后通过后面我们介绍的开发工具直接生成,这样可以减少
自己调试的时间。
------------------SpringDataJpa从入门到精通