import javax.persistence.*;
一、JPA 基本注解:@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(generator="h-uuid2")
@GenericGenerator(name = "h-uuid2",strategy="uuid2")
private String id;
@Column(name="user_name")
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
@Transient
private String temp;
...
}
----
create table t_user (
id varchar(255) not null,
password varchar(255),
regDate date,
user_name varchar(255),
primary key (id)
) engine=InnoDB
1、@Entity -- 表示实体类
说明这个类是实体类,并且使用默认的orm规则(类名即表名,类属性名即表字段名)。如果改变这种默认就使用:
@Table 改变class名与表名的映射规则,@Column 改变class中字段名与db中表的字段名的映射规则。
2、@Table -- 标识实体类表名
当实体类名和数据库表名不一致时使用 @Table 标注说明,即使表名一致,也推荐使用,提高程序的可读性 。该标注与 @Entity 标注并列使用。
属性名
释义
值
默认值
name
指定数据库表名称 若不指定则以实体类名称作为表名
字符串
“”
schema
指定该实体映射的schema
字符串
“”
catalog
与schema属性相同
字符串
“”
indexes
索引
@Index
{}
uniqueConstraints
唯一约束
@UniqueConstraint
{}
3、@Id -- 标记属性的主键
一旦标注了主键,该实体属性的值可以指定,也可以根据一些特定的规则自动生成。(一个实体中可以出现多个@Id注解,但需要@IdClass配合使用,以表示联合主键(不推荐))。
3.1 @Id -- 标识数据类型
分类
类型
Java基本数据类型
byte、int、short、long、char
Java基本数据类型对应的封装类
Byte、Integer、Short、Long、Character
大数值型类
java.math.BigInteger
字符串类型
String
时间日期型
java.util.Date、java.sql.Date
double 和 float浮点类型和它们对应的封装类不能作为主键,因为判断是否唯一是通过equals方法来判断的,不能够准确的匹配。
3.2 @GeneratedValue -- 标注主键的生成策略
属性名
释义
值
默认值
strategy
主键的生成策略
GenerationType.TABLE 通过表产生主键,框架借由表模拟序列产生主键 GenerationType.SEQUENCE 通过序列产生主键(不支持MySql) GenerationType.IDENTITY 自增长(不支持Oracle)
GenerationType.AUTO 自动选择合适的策略
GenerationType.AUTO
generator
自定义生成策略
字符串(对应@GenericGenerator注解的name属性值)
“”
需要注意的是,同一张表中自增列最多只能有一列,GenerationType.SEQUENCE在oracle数据库时使用,配合@SequenceGenerator指定使用哪个序列名(后续使用)
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY) //针对mysql数据库:自增长
private int id;
----
@Id
@GeneratedValue(strategy=GenerationType.AUTO) //根据数据库,自动选择合适的策略
private int id;
3.3 @GenericGenerator -- 自定义主键生成策略
属性名
释义
值
默认值
name
生成器名称
字符串(对应@GeneratedValue注解的generator属性值)
无
strategy
具体生成器的类名
见该表下的代码块
无
parameters
strategy生成器用到的参数
{}
@Id
@GeneratedValue(generator="h-uuid2") //自定义str: 和name值对应
@GenericGenerator(name = "h-uuid2",strategy="uuid2") //自定义策略: uuid2
private String id;
主键生成策略和各自的具体生成器之间的关系,在org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory中指定如下:
四种数据库的支持情况如下:
数据库名称
支持的id策略
mysql
GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY不支持GenerationType.SEQUENCE
oracle
strategy=GenerationType.AUTO GenerationType.SEQUENCE GenerationType.TABLE不支持GenerationType.IDENTITY
postgreSQL
GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY GenerationType.SEQUENCE 都支持
kingbase
GenerationType.TABLE GenerationType.SEQUENCE GenerationType.IDENTITY GenerationType.AUTO 都支持
4、@Column -- 标识实体类中属性与数据表中字段的对应关系。
属性名
释义
值
默认值
name
所对应表字段的名称
字符串
“”
unique
是否为唯一标识(亦可在@Table注解中设置)
布尔值
false
nullable
是否可为null值
布尔值
true
insertable
在使用’insert’时,是否插入该字段的值
布尔值
true
updatable
在使用’update’时,是否更新该字段的值
布尔值
true
columnDefinition
通过Entity生成DDL语句
字符串
“”
table
包含当前字段的表名
字符串
“”
length
字段长度(类型仅为varchar时生效)
正整数或零
255
precision
数值的总长度(类型仅为double时生效)
正整数或零
0
scale
保留小数点后数值位数(类型仅为double时生效)
正整数或零
0
提示:此注解可以标注在getter方法或属性前。
5、 @Temporal -- 指明该属性获取时间精度
默认为 TemporalType.TIMESTAMP 类型。
类型
说明
java.sql.Date
日期型,精确到年月日,例如“2008-08-08”
java.sql.Time
时间型,精确到时分秒,例如“20:00:00”
java.sql.Timestamp
时间戳,精确到纳秒,例如“2008-08-08 20:00:00.000000001”
//@Temporal(TemporalType.DATE) //表中类型: date
//@Temporal(TemporalType.TIMESTAMP) //表中类型: datetime
@Temporal(TemporalType.TIME) //表中类型: time
private Date regDate;
6、@Transient -- 属性不与表字段映射
一旦变量被transient修饰,属性将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问(即:不与表字段映射)。 常用于某属性仅为临时变量时。
7、@Basic
表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的属性,默认即为 @Basic。
属性名
释义
值
默认值
fetch
加载方式
FetchType.EAGER 即时加载 FetchType.LAZY 延迟加载
FetchType.EAGER
strategy
是否可为null
布尔值
true
hibernate 的xml配置默认为:懒加载, JPA 注释配置默认为:立即加载。
对于一些特殊的属性,比如长文本型text、字节流型blob型的数据,在加载Entity时,这些属性对应的数据量比较大,有时创建实体时如果也加载的话,可能严重造成资源的占用。要想解决这些问题,此时就可设置实体属性的加载方式为延迟加载(LAZY)
二、JPA 映射注解:
1、单向多对一关联
多个角色对应一个用户。 多:添加一的类对象关联属性;一:不做变化
注意:注解 @ManyToOne(fetch=FetchType.EAGER) 默认的是立即加载,需要懒加载的时候,修改fetch参数
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")
private User user; //关联属性
...
}
-----
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
...
}
2、单向一对多的关联
一个用户对应多个角色。 一:添加多的类对象集合关联属性;多:不做变化
注意:注解@OneToMany(fetch=FetchType.LAZY)默认的是懒加载,需要立即加载的时候,修改fetch参数
删除1这端的记录时,可以删除,然后会把多端的外键设置为null,需要级联删除可以设置@OneToMany(设置cascade属性)
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
@OneToMany(fetch=FetchType.LAZY,cascade= {CascadeType.REMOVE})
@JoinColumn(name="user_id")
private Set roles = new HashSet();
...}
----
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
...}
3、双向的一对多(多对一)的关联
一这端:user,多这端:role
注意:
1)双向关联关系,两遍默认都会维护关系,可能冲突,也影响效率,正常情况关系交给“多”这端维护,一这端配置mappedBy属性则放弃@OneToMany(mappedBy="user")值为多这端关联属性的属性名
2)一旦一这端使用 mappedBy 属性,那么@JoinColumn这个注解就不能使用了,用了会出错
3)需要级联操作可以设置@OneToMany(设置cascade属性),不设置放弃维护的这端删除不了
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
//mappedBy="user" 一这端放弃维护关联关系, 值为多这端关联属性的属性名
@OneToMany(fetch=FetchType.LAZY,cascade= {CascadeType.ALL},mappedBy="user")
private Set roles = new HashSet();
...}
----
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
@ManyToOne(fetch=FetchType.EAGER,cascade={CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name="user_id")
private User user;
...}
4、双向的一对一的关联
双向关联,需要一边要放弃关系维护
注意:
1)负责维护关系的一端,要配置唯一约束 unique=true,因为一对一关联,两边都是唯一的
2) 默认关联策略是:立即加载
3)需要级联操作可以设置@OneToOne(设置cascade属性),不设置放弃维护的这端删除不了
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
@OneToOne(mappedBy="user",cascade= {CascadeType.ALL})
private Role role;
...}
----
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
@OneToOne
@JoinColumn(name="user_id",unique=true)
private User user;
...}
5、双向多对多的关联
双向关联,需要一边要放弃关系维护
注意:
1) 默认关联策略是:立即加载
2)需要级联操作可以设置@ManyToMany(设置cascade属性),不设置放弃维护的这端删除不了
3) 关联中间表,无法自定义字段,不灵活,
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
@ManyToMany(mappedBy="users",cascade=CascadeType.ALL)
private Set roles = new HashSet();
...}
----
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
@ManyToMany
@JoinTable(name="t_user_role",
joinColumns = {@JoinColumn(name="t_user",referencedColumnName="id")},
inverseJoinColumns = {@JoinColumn(name="t_role",referencedColumnName="id")}
)
private Set users = new HashSet();
...}
注意:在真项目开发中,处理双向多对多的关联,一般变通来处理,将对对多关联,转换为两个一对多的关联,中间表可以自定义字段。
转换为两个双向一对多实例@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String username;
private String password;
@Temporal(TemporalType.DATE) //表中类型: date
private Date regDate;
@OneToMany(mappedBy="user",cascade=CascadeType.ALL)
private Set userRoles = new HashSet();
...}
----
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="role_name")
private String roleName;
private String state;
@OneToMany(mappedBy="role",cascade=CascadeType.ALL)
private Set userRoles = new HashSet();
...}
--中间表--
@Entity
@Table(name="t_user_role")
public class UserRole {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private Date createDate;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="user_id")
private User user;
@ManyToOne
@JoinColumn(name="role_id")
private Role role;
...}
注意:
1) 需要级联操作可以设置@OneToMany(设置cascade属性),不设置放弃维护的这端删除不了
2) 关联中间表,可自定定义字段,
end...