JPA常用註解彙總紀要

bladestone發表於2019-03-07

註解Column詳解

Column的主要屬性資訊:

  • name 自定義資料庫的欄位名稱
  • nullable 是否為空
  • length: 如果是字元型,可以限定長度
  • unqiue 是否為唯一性
  • precision/scale 對於小數的精度控制
  • insertable/updatable 可插入/可更新設定

@Column用來建立模型物件與資料庫表欄位之間的對映關係,可以使用在方法和屬性上。

在不做宣告的情況下,預設會建立與資料庫的對映。

詳細的資訊可以參閱其原始碼的說明:

/**
 * Specifies the mapped column for a persistent property or field.
 * If no <code>Column</code> annotation is specified, the default values apply.
 *
 * <blockquote><pre>
 *    Example 1:
 *
 *    &#064;Column(name="DESC", nullable=false, length=512)
 *    public String getDescription() { return description; }
 *
 *    Example 2:
 *
 *    &#064;Column(name="DESC",
 *            columnDefinition="CLOB NOT NULL",
 *            table="EMP_DETAIL")
 *    &#064;Lob
 *    public String getDescription() { return description; }
 *
 *    Example 3:
 *
 *    &#064;Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
 *    public BigDecimal getCost() { return cost; }
 *
 * </pre></blockquote>
 *
 *
 * @since Java Persistence 1.0
 */ 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface Column {

    /**
     * (Optional) The name of the column. Defaults to 
     * the property or field name.
     */
    String name() default "";

    /**
     * (Optional) Whether the column is a unique key.  This is a 
     * shortcut for the <code>UniqueConstraint</code> annotation at the table 
     * level and is useful for when the unique key constraint 
     * corresponds to only a single column. This constraint applies 
     * in addition to any constraint entailed by primary key mapping and 
     * to constraints specified at the table level.
     */
    boolean unique() default false;

    /**
     * (Optional) Whether the database column is nullable.
     */
    boolean nullable() default true;

    /**
     * (Optional) Whether the column is included in SQL INSERT 
     * statements generated by the persistence provider.
     */
    boolean insertable() default true;

    /**
     * (Optional) Whether the column is included in SQL UPDATE 
     * statements generated by the persistence provider.
     */
    boolean updatable() default true;

    /**
     * (Optional) The SQL fragment that is used when 
     * generating the DDL for the column.
     * <p> Defaults to the generated SQL to create a
     * column of the inferred type.
     */
    String columnDefinition() default "";

    /**
     * (Optional) The name of the table that contains the column. 
     * If absent the column is assumed to be in the primary table.
     */
    String table() default "";

    /**
     * (Optional) The column length. (Applies only if a
     * string-valued column is used.)
     */
    int length() default 255;

    /**
     * (Optional) The precision for a decimal (exact numeric) 
     * column. (Applies only if a decimal column is used.)
     * Value must be set by developer if used when generating 
     * the DDL for the column.
     */
    int precision() default 0;

    /**
     * (Optional) The scale for a decimal (exact numeric) column. 
     * (Applies only if a decimal column is used.)
     */
    int scale() default 0;
}

日期型別定義

Date: @Temperal(TemperalType.TIMESTAMP/DATE/TIME)
示例如下:

   @Column(name = "created_time")
   @Temporal(TemporalType.TIMESTAMP)
   private Date createdTime;

列舉型別

定義列舉類, 其有兩個值:Male/Female

  public enum Gender {
         Female, Male
  }

領域物件的列定義:

   @Column(name="t_gender", nullable=false)
   @Enumerated(EnumType.ORDINAL)
   private Gender gender;

上述列定義中EnumType支援String/Ordinal型別, String是列舉的字元描述值,Ordinal是其位置資訊,例如Female其位置為0, Male的位置為1,其存入資料庫的值即為0/1.

如果需要自定義列舉的值,例如Female之時,存入10, Male之時,存入20.該如何來處理呢?

首先重新定義列舉類:

@Getter
public enum Gender {
	Male("Male", 20), Female("Female", 10);

	private String name;
	private Integer index;
	
	private Gender(String name, Integer index) {
        this.name = name;
        this.index = index;
	}
	
	public static Gender fromInteger(Integer indexNum) {
	    Objects.requireNonNull(indexNum);
	    if (indexNum.intValue() == Female.index.intValue()) {
	    	return Female;
	    }
	    else 
	    	return Male;
	}
}

在列舉類中,定義了構造方法和一個靜態方法,基於index值獲取對應的列舉物件。
自定義Gender類的Coverter轉換器:

@Converter
public class GenderConverter implements AttributeConverter<Gender, Integer> {
    @Override
    public Integer convertToDatabaseColumn(Gender attribute) {
        return attribute.getIndex();
    }
 
    @Override
    public Gender convertToEntityAttribute(Integer dbData) {
        return Gender.fromInteger(dbData);
    }
}

注意這裡的範型使用<Gender, Integer>,第一個是列舉類,第二個是Index型別。
這個Converter將用來轉化Gender的列舉型別。

宣告使用Converter來自動轉化Gender的Domain物件值,示例如下:

    @Column(nullable=false, name="gender")
    @Convert(converter = GenderConverter.class)
    private Gender gender = Gender.Male;

這裡Gender型別的屬性設定了預設值Male,通過@Convert註解來宣告使用GenderConverter轉化類。

儲存空間大的資料型別

@Lob: 用來宣告欄位需要大的儲存空間。
如果宣告瞭String型別, 則在資料庫中預設對映為LongText。
對於二進位制資料,domain物件使用byte/Byte[], 則資料庫中型別對映為LongBlob。

由於此欄位比較大,如果直接載入,則會消耗很大記憶體。如果設定為延遲載入,則會更為人性化,可以通過@Basic(fetch=LAZY/EAGER)設定為延遲載入:
使用示例如下:

  @Lob
  @Basic(fetch=LAZY)
  private Byte[] file;

排除持久化欄位宣告

@Transient 欄位名稱
預設使用欄位對映, 通過@Transient設定,不用資料庫欄位的對映。

相關文章