JPA 标记总结
1.@Entity
通过注释@Entity或者(@Entity())表示被标示的类对应数据库中的一张表。
@Entitypublic class TravelProfile {...}上面的例子告诉O/R映射引擎,类TravelProfile是可以持久化的,同时它对应数据库中的一张表。但是它没有指明对应哪个数据库中的哪张表。
@Target({TYPE}) @Retention(RUNTIME)public @interface Table {String name() default "";String catalog() default "";String schema() default "";UniqueConstraint[] uniqueConstraints() default {};}Name:指明表的名字。(可选)
@Entity@Table(name="CUST", schema="RECORDS")public class Customer { ... }
@Target({}) @Retention(RUNTIME)public @interface UniqueConstraint {String[] columnNames();}columnNames:制定唯一约束的字段。
@Entity@Table(name="EMPLOYEE",uniqueConstraints=@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"}))public class Employee { ... }上面的例子,唯一约束标记指定字段EMP_ID和字段EMP_NAME在表中EMPLOYEE中是唯一的。
Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Column {String name() default "";boolean unique() default false;boolean nullable() default true;boolean insertable() default true;boolean updatable() default true;String columnDefinition() default "";String table() default "";int length() default 255;int precision() default 0; // decimal precisionint scale() default 0; // decimal scale}Name:指定字段名。
@Column(name="DESC", nullable=false, length=512)public String getDescription() { return description; }@Column(name="DESC",columnDefinition="CLOB NOT NULL",table="EMP_DETAIL")@Lobpublic String getDescription() { return description; }@Column(name="ORDER_COST", updatable=false, precision=12, scale=2)public BigDecimal getCost() { return cost; }2.4@JoinColumn标记
@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 "";}Name:指定外键字段名,缺省的名字是被引用实体在引用实体内部的属性标量名或域名加上下划线”_”,再加上被引用实体的主键字段名构成。
@ManyToOne@JoinColumn(name="ADDR_ID")public Address getAddress() { return address; }2.5@JoinColumns标记
@ManyToOne@JoinColumns({@JoinColumn(name="ADDR_ID", referencedColumnName="ID"),@JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")})public Address getAddress() { return address; }
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Id {}下面例子通过标记@Id初始化实体的主键为id,也可以通过加上标记@Column(name=”PrimaryKey”)自定义表的主键。
@Idpublic Long getId() { return id; }
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface GeneratedValue {GenerationType strategy() default AUTO;String generator() default "";}
public enum GenerationType { TABLE, SEQUENCE, IDENTITY, AUTO };策略类型为枚举类型,共有四种类型分别为:TABLE, SEQUENCE, IDENTITY, AUTO。
@Id@GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")@Column(name="CUST_ID")public Long getId() { return id; }@Id@GeneratedValue(strategy=TABLE, generator="CUST_GEN")@Column(name="CUST_ID")Long id;
@Target({TYPE}) @Retention(RUNTIME)public @interface IdClass {Class value();}下面例子中,复合主键类为EmployeePK,包含域empName和birthday类型分别为String,Date。
@IdClass(com.jl.hr.EmployeePK.class)@Entitypublic class Employee {@Id String empName;@Id Date birthDay;2.9@Transient标记
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Transient {}
@Entitypublic class Employee {@Id int id;@Transient User currentUser;...}2.10@Version标记
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Version {}
@Version@Column(name="OPTLOCK")protected int getVersionNum() { return versionNum; }2.11@Lob标记
@Lob@Column(name="REPORT")protected String report;@Lob @Basic(fetch=LAZY)@Column(name="EMP_PIC", columnDefinition="BLOB NOT NULL")protected byte[] pic;
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Enumerated {EnumType value() default ORDINAL;}public enum EnumType {ORDINAL,STRING}如果标记没有显性给出或者EnumType没有指定,那枚举类型默认为ORDINAL数字标识。例如:
public enum EmployeeStatus {FULL_TIME, PART_TIME, CONTRACT}public enum SalaryRate {JUNIOR, SENIOR, MANAGER, EXECUTIVE}@Entity public class Employee {...public EmployeeStatus getStatus() {...}@Enumerated(STRING)public SalaryRate getPayScale() {...}...}上面例子中,定义了两个枚举类型EmployeeStatus和SalaryRate。在实体两个属性status类型为 EmployeeStatus,而payScale为SalaryRate类型。其中一个显性给出了标记@Enumerated(STRING)来说明枚举类型的值当成字符串使用,而默认的是从1开始的数字来标识的。也可以通过标记@Enumerated(ORDINAL)指示枚举里面类型的值是数字类型的。例如在EmployeeStatus
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface ManyToOne {Class targetEntity() default void.class;CascadeType[] cascade() default {};FetchType fetch() default EAGER;boolean optional() default true;}public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH};targetEntity:表示相关联的实体类。
@ManyToOne(optional=flase)@JoinColumn(name="CUST_ID", nullable=false, updatable=false)public Customer getCustomer() { return customer; }2.14@OneToOne标记
@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 "";}前面四个选项和8.2.13中的意义是一样的。
@OneToOne(optional=false)@JoinColumn(name="CUSTREC_ID", unique=true, nullable=false, updatable=false)public CustomerRecord getCustomerRecord() { return customerRecord; }在实体CustomerRecord相关代码如下:
@OneToOne(optional=false, mappedBy="customerRecord")public Customer getCustomer() { return customer; }因为CustomerRecord是关系的非拥有者所有mappedBy只能在这边出现。
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface OneToMany {Class targetEntity() default void.class;CascadeType[] cascade() default {};FetchType fetch() default LAZY;String mappedBy() default "";}值得注意的是表示关联实体的集合要使用范形来制定集合内部的关联实体,否则必须要指定targetEntity的实体类型。Fetch类型默认为LAZY而@OneToOne和ManyToOne则默认的为EAGER。
@OneToMany(cascade=ALL, mappedBy=”customer”)public Set<Order> getOrders() { return orders; }
@ManyToOne@JoinColumn(name="CUST_ID", nullable=false)public Customer getCustomer() { return customer; }
public @interface JoinTable {String name() default "";String catalog() default "";String schema() default "";JoinColumn[] joinColumns() default {};JoinColumn[] inverseJoinColumns() default {};UniqueConstraint[] uniqueConstraints() default {};}Name:指定连接表的名字。
@JoinTable(name="CUST_PHONE",joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"),inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID"))上面例子,连接表的名字为CUST_PHONE里面有两个外键,一个来自关系拥有方的主键ID对应外键为CUST_ID;另一个是来自于关系的非拥有方的主键ID对应外键为PHONE_ID。
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface ManyToMany {Class targetEntity() default void.class;CascadeType[] cascade() default {};FetchType fetch() default LAZY;String mappedBy() default "";}各个属性的意义和标记@OneToMany是一样的,请参照8.2.1.15。
@ManyToMany@JoinTable(name="CUST_PHONES")public Set<PhoneNumber> getPhones() { return phones; }在实体PhoneNumber中为:
@ManyToMany@JoinTable(name="CUST_PHONE",joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"),inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID"))public Set<PhoneNumber> getPhones() { return phones; }@ManyToMany(mappedBy="phones")public Set<Customer> getCustomers() { return customers; }2.18@OrderBy标记
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface OrderBy {String value() default "";}对于使用该标记对应的字段必须是可以比较的,默认的使用的是ASC也可以根据需求改变成DESC。当没有指定value的时候,那默认的就是对实体的主键进行排序,例如:
Entity public class Course {...@ManyToMany@OrderBy("lastname ASC")public List<Student> getStudents() {...};...}@Entity public class Student {...@ManyToMany(mappedBy="students")@OrderBy // PK is assumedpublic List<Course> getCourses() {...};...}