最近一直在使用jpa,特此对用到的注解做个记录,方便以后查询
参考:JPA 批注参考
什么是JPA
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它不囿于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范.
JPA的总体思想和现有Hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
(1)ORM映射元数据
JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
(2)JPA 的API
用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
(3)查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
@Entity 标注实体类
@Table 默认情况下生成的表名为实体类的名称,通过属性name可以修改表名
@Id 标注实体类中的属性为映射表中的主键
@GeneratedValue 与@Id一起使用,设置主键的生成策略,对于mysql,可以使用@GeneratedValue(strategy=GenerationType.INENTITY)指定主键自增策略;对于Oracle,使用@GeneratedValue(Strategy=GenreationType.SEQUENCE,generator=“seq_tbl_person”)指定序列策略,其中generator表示生成器的名字,而且还要指定@SequenceGenerator(name="seq_tbl_person",sequenceName="seq_tbl_person",allocationSize=1)注解配合使用,其中name指定生成器的名字,对应@GEneratedValue中的generator属性值,sequenceName指定数据库中定义序列的名字,allocationSize指定序列每次增长1,类似于hibernate中的@GeneratedValue(generator="generator")配合@GenericGenerator(name="generator",strategy="native")使用方法
@Column 描述实体类属性映射到数据库表中对应字段的定义
属性name表示数据库表中该字段的名称,默认与实体类的属性名一致;
属性nullable表示该字段是否允许为null,默认为true;
属性unique表示该字段是否允许包含重复值,默认为false,如果不允许该列包含重复值,可以把unique设为true;
属性length表示String类型字段的大小,默认值为255;
属性insertable表示在ORM框架执行插入操作时,该字段是否应出现在INSERT语句中,默认为true,如果该列不应包含在这些语句中,就将insertable设置为false;
属性updateable表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true,如果该列不应包含在这些语句中,就将updateable设置为 false。
对于一经创建就不可以更改的字段,该属性非常有用,如对于createdAt字段。
属性columnDefinition指定该实体类属性在数据库中的实际类型,通常ORM框架可以根据属性类型自动判断数据库中字段的类型,比如String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型,该属性非常有用。同时,还可以通过该属性设置字段的缺省值,比如@Column(nullable=false,columnDefiniton="int default 0")
@OrderBy 常与@OneToMany 和 @ManyToMany一起使用,指定按一个或多个字段进行排序,属性value默认按关联实体的主键以升序顺序检索 Collection
关联的成员。下面的例子指定方法 getEmployees
应按 Employee
字段lastname
以升序顺序并按 Employee
字段 seniority
以降序顺序返回 Employee
的 List
。
@ManyToMany @OrderBy("lastname ASC", "seniority DESC") public ListgetEmployees(){...}
@Transient 指定ORM框架忽略该属性,不进行映射,ORM框架默认其注解为@Basic,对于那些不需要通过数据库查找,而只需要在运行时临时设置填充的属性,该注解非常有用。
@Enumerated 用于保存枚举常量的序数值或String值到数据库中,属性value默认值为EnumType.ORDINAL,保存序数值,如果需要持久保存枚举常量的 String 值,就将value值设为EnumType.STRING,比如下面的例子
public enum Gender implements BaseEnum {
MALE(0),
FEMALE(1),
SECRET(2);
private int value;
Gender(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public static Gender valueOf(int value){
for(Gender g : Gender.values()){
if(g.getValue() == value)
return g;
}
return null;
}
}
在User实体类中存在属性
@Enumerated(EnumType.ORDINAL) @Column(nullable = false, columnDefinition = "int default 2") private Gender gender;
@Temporal 指定为 java.util.Date
和java.util.Calendar
类型的属性持久保存的数据库类型。通过属性value设置相对应的数据库类型,TemporalType.DATE等于java.sql.Date,TemporalType.Time等于java.sql.Time,TemporalType.TIMESTAMP等于java.sql.Timestamp
@Lob 持久化大型对象到数据库中,没有属性,对于基于字符串和字符的类型,默认值为Clob(Oracle中),即字符型大型对象(Character Large Object),与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作等),在其他情况下,默认值为Blob,即二进制大型对象(Binary Large Object),适用于存贮非文本的字节流数据(如程序、图象、影音等)
@OneToOne 一对一关系映射
User类(外键拥有方):
@OneToOne(optional=false,cascade={CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH}) //可以用CascadeType.ALL替代 @JoinColumn(name="avatar_id")
private Avatar avatar;
Avatar类(被拥有方):
@OneToOne(optional=false,mappedBy="avatar")
private User user;
CascadeType
实例,其中包括:mappedBy
元素设置为拥有此关系的字段或属性的 String
名称targetEntity
元素设置为作为关系目标的实体的 Class
。@OneToMany 一对多关系映射,标注集体类型,在数据库中并没有实际字段
@ManyToOne 多对一关系映射,标注的属性通常是数据库的外键
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, mappedBy = "user") private Listnotes; //User类中 @ManyToOne(cascade = {CascadeType.REFRESH}, optional = false) @JoinColumn(name = "user_id") private User user; //Note类中
@ManyToMany 多对多关系映射,一般很少用,遇到了都是拆分成两个一对多,比如一个用户可以喜欢很多的文章,一篇文章又可以被很多的用户喜欢,二者之间的关系就是多对多的关系,一般我们会创建一个新的实体类UserLikeNote,设计如下:
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE}, mappedBy = "user") private ListuserLikeNotes; //User类中
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE}, mappedBy = "note") private ListuserLikeNotes = new ArrayList<>(); //Note类中
@ManyToOne(cascade = {CascadeType.REFRESH},optional = false) private User user; //UserLikeNote类中
@ManyToOne(cascade = {CascadeType.REFRESH},optional = false) private Note note; //UserLikeNote类中
仔细想想,这个例子可能不太恰当,举个典型的多对多应用吧,用户和角色
@ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER) @JoinTable(name = "t_user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Listroles; //User类中
@ManyToMany(mappedBy = "roles") private Listusers; //Role类中
安利一个trick,@OneToMany和@ManyToMany(以Many结尾的fetch默认值都是FetchType.LAZY),而@OneToOne和@ManyToOne(fetch的默认值为FetchType.EAGER)
看一下这几个注解的源码:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.LAZY;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.LAZY;
String mappedBy() default "";
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.EAGER;
boolean optional() default true;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.EAGER;
boolean optional() default true;
}
参考博文:
JPA实体类中的注解