JPA注解详解

基于 hibernate-jpa-2.1-api ,mysql数据库

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<Role> 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<Role> 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<Role> 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<User> 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<UserRole> 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<UserRole> 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...

猜你喜欢

转载自blog.csdn.net/qq_42402854/article/details/83117199