JPA与Hibernate注解完全指南:Java持久化开发详解
在将Java对象映射到数据库表、列等时,使用JPA注解。Hibernate是JPA规范中最流行的实现,并提供了一些额外的注解。今天我们将浏览JPA注解以及带有简短代码片段的Hibernate注解。
JPA注解 – Hibernate注解

<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
Java对象到数据库表的JPA注解映射
让我们来看一些重要的JPA注解。请注意,这些注解位于javax.persistence包中。
- @Entity:指定类为实体。该注释可以应用于类、接口或枚举。
import javax.persistence.Entity;
@Entity
public class Employee implements Serializable {
}
- @Table:指定实体与数据库中的哪个表进行映射。在下面的示例中,数据将存储在名为”employee”的表中。@Table注释的name属性用于指定表名。
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
}
- @Column:使用@Column注释指定列映射。此注释的name属性用于指定表的列名。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Column(name = "employee_name")
private String employeeName;
}
- @Id:此注释指定实体的主键。
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
private int id;
}
- @GeneratedValue:此注释指定主键值的生成策略。
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy=SEQUENCE, generator="ID_SEQ")
private int id;
}
- @Version:可以使用此注释控制版本或并发性。
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Version
@Column(name = "version")
private Date version;
}
- @OrderBy:使用@OrderBy注释对数据进行排序。在下面的示例中,它将按照id的升序对所有employees_address进行排序。
@OrderBy("id asc")
private Set employee_address;
- @Transient:除非您使用@Transient注释对其进行标注,否则实体的每个非静态和非瞬态属性都被视为持久化属性。
@Transient
Private int employeePhone;
- @Lob:使用@Lob声明大对象。
@Lob
public String getEmployeeAddress() {
return employeeAddress;
}
上述的注解集是最常用的JPA注解,用于定义一个实体。
映射表之间的Hibernate注解
我们有另一组注解,用于指定不同表格和实体之间的关联映射。我们将以下述场景为例进行说明。
- 表’employee’和’employeeDetail’具有一对一关联,它们共享相同的主键。
- 表’communication’和’communicationDetail’通过外键链接。这也是一对一关联。
- 表’communication’和’employee’使用外键以多对一关联链接,其中communication是拥有方。
- 表’employee’和’employeeStatus’通过外键以多对一关联链接,其中employee是拥有方。
@OneToOne Employee和EmployeeDetail实体共享相同的主键,我们可以使用@OneToOne和@PrimaryKeyJoinColumn来关联它们。在这种情况下,EmployeeDetail的id属性没有使用@GeneratedValue进行注释。Employee的id值将用于EmployeeDetail的id。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@Entity
@Table(name = "employeeDetail")
public class EmployeeDetail implements Serializable {
@Id
@Column(name = "id")
private int id;
}
请注意以下要点:
- @PrimaryKeyJoinColumn应该用于关联共享相同主键的实体。
- 当外键由其中一个实体持有时,应使用@JoinColumn和@OneToOne的mappedBy属性。
通信和通信详细信息通过外键连接,因此可以使用@OneToOne和@JoinColumn注解。在下面的代码段中,为通信生成的ID将映射到”communication_id”列的通信详细信息表中。同样使用@MapsId注解实现。
@Entity
@Table(name = "communicationDetail")
public class CommunicationDetail implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
}
@Entity
@Table(name = "communication")
public class Communication implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue
private Integer id;
@OneToOne(mappedBy = "communication", cascade = CascadeType.ALL)
private CommunicationDetail communicationDetail;
}
许多员工可以共享相同的状态,因此员工到员工状态之间是多对一的关系。可以使用@ManyToOne注解来表示相同的关系。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
}
通过@OneToMany注解,Employee和Communication之间将建立一个一对多的关系。这个关系的拥有者是Communication,所以在Employee实体中我们会使用’mappedBy’属性来实现双向关联。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)
@OrderBy("firstName asc")
private Set communications;
}
@PrimaryKeyJoinColumn此注解用于将共享相同主键的实体关联起来。
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@JoinColumn注解用于一对一或多对一关联,当外键由实体中的一个持有时使用。
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
@JoinTable: 通过使用@JoinTable和mappedBy,可以将实体通过关联表进行链接。
@MapsId: 可以使用@MapsId注解将具有共享键的两个实体持久化。
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
继承映射的Hibernate注解
现在让我们尝试理解Hibernate中的继承映射注释。Hibernate支持三种基本的继承映射策略。
- 每个类层次结构一个表
- 每个子类一个表
- 每个具体类一个表
我们将为每种类型考虑一个例子。
1. 每个类层次结构一个表 – 单表对类层次结构的策略。
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="cartype", discriminatorType=DiscriminatorType.STRING )
@DiscriminatorValue("Car")
public class Car { }
@Entity
@DiscriminatorValue("BMW")
public class BMW extends Car { }
2. 每个子类一个表 – 连接的子类策略。
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Ship implements Serializable {}
@Entity
@PrimaryKeyJoinColumn
public class Titanic extends Ship {}
3. 每个具体类一个表
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Aeroplane implements Serializable {}
@DiscriminatorColumn:顾名思义,这一列是鉴别符,并且该注解指定了SINGLE_TABLE和JOINED继承映射策略的鉴别符列。
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="cartype", discriminatorType=DiscriminatorType.STRING )
以上就是关于JPA和Hibernate注解的全部内容。参考资料:JSR 338,Hibernate API文档。