@Entity
注册在类头上,将一个类声明为一个实体bean(即一个持久化POJO类) 。
@Table
注册在类头上,注解声明了该实体bean映射指定的表(table)。
@Id
用来注册主属性,标识这个属性是实体类的唯一识别的值
注意:这个注解只能标注单一列构成的主键,如tbl_grade那种有两个字段组成的联合主键由其他注解标识。
<id name= "uuid">
<generator class= "assigned"/>
</id>
@Id 只是标识这个属性是主键,但是并没有指出其生成策略,如上例中的assigned就是由程序员指定的生成策略。
如果仅仅写出@Id,即是使用assigned生成略,如:
//如果想使用Oracle支持的sequence取主键,
//必须通过@GeneratedValue来指定生成策略,
//而由@SequenceGenerator指定如何使用sequence。
@Id
@Column
@SequenceGenerator( //可以定义在属性上,也可以定义在类上
name = "generator1", //定义名为generator1的主键生成策略
sequenceName="seq_a" //引用名为数据库中名为seq_a的序列
allocationSize = 1, //每次sequence加1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE, //使用sequence生成主键
generator = "generator1" //引用下面名为gernator的生成策略
)
private int uuid;
@GeneratedValue
用来注册主属性的生成策略
示例:@GeneratedValue(strategy=GenerationType.AUTO)
strategy: 表示主键生成策略,有AUTO,INDENTITY,SEQUENCE 和 TABLE 4种, 分别表示让ORM框架自动选择,根据数据库的Identity字段生成,根据数据库表的Sequence字段生成,以有根据一个额外的表生成主键,默认为AUTO。一般我们设置为默认,也就是自动增长,即GenerationType.AUTO即可,让其自动增长,所以我们也可以不写。
generator:表示主键生成器的名称,这个属性通常和ORM框架相关,例如,Hibernate可以指定uuid等主键生成方式.一般也不写,取默认值
@Basic
可以看做是基础修饰,默认每一个属性都有。默认如果不写的话为:@Basic(fetch=FetchType.EAGER,optional=true)
fetch表示的是加载策略/读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER。但是,如果想要使用懒加载,则必须使用load方法,使用get方式是不可以的。当使用Query的时候会不会懒加载。
optional表示的是该属性是否允许为null,默认为true,即允许为null。
@Column
用来注册属性,标识属性对应的字段
@Column(
name="columnName"; (1)
boolean unique() default false; (2)
boolean nullable() default true; (3)
boolean insertable() default true; (4)
boolean updatable() default true; (5)
String columnDefinition() default ""; (6)
String table() default ""; (7)
int length() default 255; (8)
int precision() default 0; // decimal precision (9)
int scale() default 0; // decimal scale (10)
(1) name 可选,列名(默认值是属性名)
(2) unique 可选,是否在该列上设置唯一约束(默认值false)
(3) nullable 可选,是否设置该列的值可以为空(默认值false)
(4) insertable 可选,该列是否作为生成的insert语句中的一个列(默认值true)
(5) updatable 可选,该列是否作为生成的update语句中的一个列(默认值true)
(6) columnDefinition 可选: 为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植)
(7) table 可选,定义对应的表(默认为主表)
(8) length 可选,列长度(默认值255)
(8) precision 可选,列十进制精度(decimal precision)(默认值0)
(10) scale 可选,如果列十进制数值范围(decimal scale)可用,在此设置(默认值0)
@Version
标识这个属性用来映射乐观锁的version
@Transient
标识这个属性不用持久化
以上的@Id、@GeneratedValue、@Column、@Version,可以用来注册属性,既可以写在Java类的属性上,也可以注册在属性对应的getter上。@Transient注册在多余的属性或多余的getter上,但是必须与以上的@Column等对应。
@Embedded【大对象的属性头上】
Embedded将几个字段组合成一个类,并作为整个Entity的一个属性。
例如User包括id,name,city,street,zip属性。我们希望city,street,zip属性映射为Address对象。这样,User对象将具有id,name和address这三个属性。Address对象必须定义为@Embededable:
@Embeddable //可以被嵌入的
public class Address {
city,street,zip
}
@Entity
public class User {
@Embedded //将address的每一个属性嵌入到User的表中,Address类没有自己的表
public Address getAddress() {
//..........
}
}
@Enumerated
指明枚举类型的属性存储的类型(字符串、索引)
@Enumerated(EnumType.STRING)
private Gender gender=Gender.MAN;
@Lob
大文本存储。数据库存储类型为LONGTEXT
@Lob
public String info;
@MappedSuperclass
基于代码复用和模型分离的思想,在项目开发中使用JPA的@MappedSuperclass注解将实体类的多个属性分别封装到不同的非实体类中。
@MappedSuperclass注解只能标准在类上:@Target({java.lang.annotation.ElementType.TYPE})
标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
注意:对于其父类中标注@Lob注解的属性将不能重载,并且@AttributeOverride里的@Column设置都将不起作用。JPA规范中对@Lob注解并没有说明不能同时标注@Column注解,但是在实际使用中Hibernate JPA不支持这中标注方式。
//父类Cat
package com.xj.model;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class Cat {
private Long id;
private String name;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//子类1 BeijingCat
package com.xj.model;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="t_beijingcat")
public class BeijingCat extends Cat {
private String beijing;
public String getBeijing() {
return beijing;
}
public void setBeijing(String beijing) {
this.beijing = beijing;
}
}
//子类2 ShanghaiCat
package com.xj.model;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="t_shanghaiCat")
public class ShanghaiCat extends Cat {
private String shanghai;
public String getShanghai() {
return shanghai;
}
public void setShanghai(String shanghai) {
this.shanghai = shanghai;
}
}
//结果生成 两张表t_beijingcat、 t_shanghaicat
//如果不用@MappedSuperclass 而用@Entity替换的话,只会生成一张cat表,字段有:id,name,shanghaicat,bejingcat
@ManyToOne
示例:@ManyToOne(fetch=FetchType, cascade=CascadeType)
表示的是一个 多对一 的映射。该注解标注的属性通常是数据库表的外键。
//订单Order和用户User是一个ManyToOne的关系
//在Order类中定义
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
return user;
}
@JoinColumn(可选)
这个量的作用就是用来定义外键在我们这个表中的属性名。只能够在有外键处才能够使用。@JoinColumn(name=”USER”)
如果我们没有定义这个属性,则默认的外键的属性名,如:实体Order有一个user属性来关联实体User, 则Order的user属性为一个外键, 其默认的名称为实体User的名称+下划线+实体User的主键名称。
@OneToMany
描述的是一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段。
例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除
@OneTyMany(cascade=ALL)
public List getOrders() {
return orders;
}
@OneToOne
OneToOne描述的是一个一对一的关联
@OneToOne(fetch=FetchType.LAZY)
public Blog getBlog() {
return blog;
}
@ManyToMany
ManyToMany描述的是一个多对多关联。多对多关联实际上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理
User实体表示用户,Book实体表示书籍,为了描述用户收藏的书籍,可以在User和Book之间建立ManyToMany关联
@Entity
public class User {
private List books;
@ManyToMany(targetEntity=package.Book.class)
public List getBooks() {
return books;
}
public void setBooks(List books) {
this.books=books;
}
}
@Entity
public class Book {
private List users;
@ManyToMany(targetEntity=package.Users.class, mappedBy="books")
public List getUsers() {
return users;
}
public void setUsers(List users) {
this.users=users;
}
}
两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称
利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联。
标准的1:1
<!--主1【tbl_product】 -->
<one-to-one name="info" cascade="all"/>
<!--从1【tbl_product_info】 -->
<id name="uuid">
<generator class="foreign【写死,使用外来生成策略】">
<param name="property">product【引用自己的Java属性名】</param>
</generator>
</id>
<one-to-one name="product"/>
//主1【tbl_product】:
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private ProductInfoModel info;
//从1【tbl_product_info】:
@Id
@Column
@GeneratedValue(generator="copy【引用生成策略】")
@GenericGenerator(name="copy【定义生成策略】",
strategy="foreign【写死,使用外来策略】",
parameters=@Parameter(name="property",
value="product【引用自己的Java属性】")
)
private int uuid;
@OneToOne(mappedBy="info【引用对方的Java属性】")
private ProductModel product;
或者
<!-- 主1【tbl_product】-->
<one-to-one name="info" foreign-key="puuid【对方的数据库外键列名】" cascade="all"/>
<!-- 从1【tbl_product_info】-->
<many-to-one name="product" column="puuid【自己的数据库外键列名】" unique="true【写死】"/>
//主1【tbl_product】:
@OneToOne(cascade=CascadeType.ALL, mappedBy="product【对方的Java类属性名 】")
private ProductInfoModel info;
//从1【tbl_product_info】:
@OneToOne
@JoinColumn(name="puuid【自己的数据库外键列名】")
private ProductModel product;
标准的1:N
<!-- 1【tbl_parent】-->
<set name="children">
<key column="puuid【对方的数据库外键列名】"/>
<one-to-many class="cn.javass.model.c.ChildModel【对方的Java类名】"/>
</set>
<!-- 多【tbl_child】-->
<many-to-one name="parent" column="puuid【自己的数据库外键列名】"/>
//1【tbl_parent】:
@OneToMany
@JoinColumn(name="puuid【对方的数据库外键列名】")
private Set<ChildModel> children = new HashSet<ChildModel>();
//多【tbl_child】:
@ManyToOne
@JoinColumn(name="puuid【自己的数据库外键列名】")
private ParentModel parent;
标准的N:N
<set name="courses" table="tbl_grade【联接表】">
<key column="suuid【联接表里代表自己的数据库字段名】"/>
<many-to-many column="cuuid【联接表里代表对方的数据库字段名】" class="cn.javass.model.e.CourseMode【对方的类名】"/>
</set>
@ManyToMany
@JoinTable(
name="tbl_grade【联接表】",
joinColumns=@JoinColumn(name="suuid【联接表里代表自己的数据库字段名】"),
inverseJoinColumns=@JoinColumn(name="cuuid 【联接表里代表对方的数据库字段名】" )
)
private Set<CourseModel> courses = new HashSet<CourseModel>();