JPA

Java Persistence API

1. 基本注解

1.1 @Entity

@Entity 定义的对象会成为被 JPA 管理的实体,将映射到指定的数据库表中。

public @interface Entity {
    //可选,默认是此实体类名,全局唯一
    String name() default "";
}

1.2 @Table

用于指定数据库的表名。

public @interface Table {
    //表的名字,如果不写,则默认与实体的名字一样
    String name() default "";
    //此表的catalog
    String catalog() default "";
    //此表的schema
    String schema() default "";
    //唯一性约束,只有创建表的时候用,默认不需要
    UniqueConstraint[] uniqueConstraints() default {};
    //索引,只有创建表的时候使用,默认不需要
    Index[] indexes() default {};
}

1.3 @Id

定义数据库的主键,一个实体里至少有一个主键。

1.4 @IdClass

联合主键。

public @interface IdClass {
    //联合主键的类
    Class value();
}

联合主键的用处就是一个表中能存在多个主键,这些主键在关联在外部的一个对象中,这个对象需要满足以下条件

  • 必须实现 Serializable 接口
  • 必须有默认的 public 无参构造方法
  • 必须覆盖 equals()hashCode() 方法

1.5 @GeneratedValue

主键生成策略。

public @interface GeneratedValue {
    //Id生成策略,默认GenerationType.AUTO
    GenerationType strategy() default GenerationType.AUTO;
    //通过Sequences生成Id,常见的是Orcale数据库的Id生成规则,需要配合@SequenceGenerator使用
    String generator() default "";
}

public enum GenerationType {
    //通过表产生主键,框架由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
    TABLE,
    //通过序列产生主键,通过@SequenceGenerator注解指定序列名,Mysql不支持这种方式
    SEQUENCE,
    //采用数据库Id自增,用于Mysql数据库
    IDENTITY,
    //JPA默认选项,自动选择策略
    AUTO;

    private GenerationType() {
    }
}

1.6 @Basic

@Basic 表示属性是到数据库的字段的映射,如果实体的字段上没有任何注解,默认为 @Basic

public @interface Basic {
    //EAGER是立即加载,这是默认方式,可以看到还有一种LAZY懒加载
    FetchType fetch() default FetchType.EAGER;
    //Optional 类是一个可以为null的容器对象,设置为true,则表示字段可以为null,默认可以
    boolean optional() default true;
}

public enum FetchType {
    LAZY,
    EAGER;

    private FetchType() {
    }
}

1.7 @Transient

@Transient 表示该属性并非一个到数据库表的字段的映射,是非持久化属性,与 @Basic 作用相反。

实体中有数据库中不存在的字段,可以加上 @Transient 注解,忽略这个字段的映射。

1.8 @Column

public @interface Column {
    String name() default "";
    //表示该字段是否为唯一标识,默认为false,如果表中有一个字段需要唯一标识,则既可以使用该标记,也可以使用@Table标记中的@UniqueConstraint
    boolean unique() default false;
    //数据字段是否允许为空,默认允许
    boolean nullable() default true;
    //执行insert操作时是否包含此字段,默认包含
    boolean insertable() default true;
    //执行update操作时是否包含此字段,默认包含
    //insertable和updatable属性一般多用于只读的属性,例如主键和外键等。这些字段的值通常是自动生成的
    boolean updatable() default true;
    //表示创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用
    String columnDefinition() default "";
    //表示当映射多个表时,指定表的表中的字段。默认值为主表的表名
    String table() default "";
    //字段长度,默认255
    int length() default 255;
    // precision 属性和 scale 属性表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数
    int precision() default 0;
    int scale() default 0;
}

1.9 @Temporal

@Temporal 用来设置 Date 类型的属性映射到对应精度的字段,也就是对日期进行格式化。

public enum TemporalType {
    DATE,
    TIME,
    TIMESTAMP;

    private TemporalType() {
    }
}

public @interface Temporal {
    TemporalType value();
}

public enum TemporalType {
    DATE,
    TIME,
    TIMESTAMP;

    private TemporalType() {
    }
}

可以看到有三种格式化方式,

  1. @Temporal(TemporalType.DATE): 实体类会封装成日期 yyyy-MM-dd 的 Date 类型。
  2. @Temporal(TemporalType.TIME): 实体类会封装成时间 hh-MM-ss 的 Date 类型。
  3. @Temporal(TemporalType.TIMESTAMP): 实体类会封装成完整的时间 yyyy-MM-dd hh:MM:ss 的 Date 类型。

1.10 @Enumerated

用于直接映射枚举类型的字段。

public @interface Enumerated {
    EnumType value() default EnumType.ORDINAL;
}

1.11 @Lob

@Lob 将属性映射为数据库支持的大对象类型,支持以下两种数据库类型的字段。

  • Clob:长字符串类型,java.sql.ClobCharacter[]char[]String 都将被映射成 Clob 类型。
  • Blob:字节类型,java.sql.BlobByte[]byte[]、实现了 Serializable 接口类型都将被映射成 Blob 类型。

2. JPA 中的实体关系

简单地用原始字段持久化一个对象只是等式的一半。JPA 还具有管理彼此相关的实体的能力。表和对象中都可能存在四种实体关系:

  • 一对多
  • 多对一
  • 多对多
  • 一对一

2.1 @JoinColumn

定义外键关联的字段名称。

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(ConstraintMode.PROVIDER_DEFAULT);
}

配合 @OneToOne@OneToMany@ManyToOne 一起使用。

2.2 关系映射注解

public @interface OneToOne {
    //关系目标实体,默认为该字段的类型
    Class targetEntity() default void.class;
    
    //级联操作策略
    CascadeType[] cascade() default {};

    //数据获取方式,立即加载和延迟加载
    FetchType fetch() default FetchType.EAGER;

    boolean optional() default true;

    //关联关系被谁维护,一般不需要特别指定, 只有关系维护方才能操作两者的关系,被维护方即使设置了维护方属性进行存储也不会更新外键关联
    //mappedBy不能与@JoinColumn或者@JoinTable同时使用
    //mappedBy的值是指另一方的实体里属性的字段,而不是数据库字段,也不是实体的对象的名字,是另一方配置了@JoinColumn或者@JoinTable注解的属性的字段名称
    String mappedBy() default "";

    //是否级联删除,和 CascadeType.REMOVE 的效果一样,只是配置了两种中的一种就会自动级联删除
    boolean orphanRemoval() default false;
}

public enum CascadeType { 
    ALL, 
    PERSIST, 
    MERGE, 
    REMOVE,
    REFRESH
}

级联操作策略代码举例解释

public class Student {
    @ManyToMany(cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
    private Set courses = new HashSet<>();
}
  1. CascadeType.PERSIST 级联新建:若 Student 实体持有的 Course 实体在数据库中不存在时,Student 保存时自动在 Course 实体对应的数据库中保存 Course 数据。
  2. CascadeType.MERGE 级联更新:当 Student 中的数据改变,会相应地更新 Course 中的数据。
  3. CascadeType.REMOVE 级联删除:删除 Student 实体,与它有映射关系的 Course 实体也会跟着被删除。
  4. CascadeType.REFRESH 级联刷新:Student 保存时重新加载 Course 关系
  5. CascadeType.DETACH 级联脱离:要删除一个实体,直接撤销所有相关的外键关联
  6. CascadeType.ALL 拥有以上所有级联操作权限
  7. 默认,关系表不会产生任何影响

@OneToOne 需要配合 @JoinColumn 一起使用

在使用@OneToOne进行双向关联时,需要在类上加上注解 @JsonIdentityInfo,这个注解被用来在序列化/反序列化时为该对象或字段添加一个对象识别码,通常是用来解决循环嵌套的问题。通过配置属性 generator 来确定识别码生成的方式,配置属性 property 来确定识别码的名称,识别码名称没有限制。

一般这个注解可以这么加

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")

@OneToMany@ManyToOne 同上。

2.3 @OrderBy

用于关联查询时排序。

@Entity 
public class Course {
    ...
    @ManyToMany
    @OrderBy("lastname ASC")
    public List  getStudents() {...};
    ...
}

@Entity 
public class Student {
    ...
    @ManyToMany(mappedBy="students")
    @OrderBy //默认使用主键排序
    public List  getCourses() {...};
    ...
}

3. 查询

注意: 这里是接口,是 persistence-api 包中的,项目里 Repository 里的接口上面实现的 @Query 注解不是下面这个,spring-data-jpa 的查询和解析留待下回分解

/**
 * 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);
}

你可能感兴趣的:(JPA)