Java注解在Hibernate中的应用
2022-06-216.2k 阅读
Java注解概述
Java注解(Annotation)是从Java 5.0开始引入的一种元数据(Metadata)形式,它提供了一种安全的类似注释的机制,用于为程序元素(类、方法、成员变量等)设置元数据。注解本质上是一种接口,该接口默认继承自java.lang.annotation.Annotation
接口。
注解有多种类型,常见的包括:
- 标记注解(Marker Annotation):这类注解没有成员变量,仅仅起到标记作用。例如
@Override
,它用于标记一个方法,告诉编译器这个方法是重写父类中的方法。如果方法签名与父类方法不匹配,编译器会报错。
class Parent {
public void print() {
System.out.println("Parent print");
}
}
class Child extends Parent {
@Override
public void print() {
System.out.println("Child print");
}
}
- 单值注解(Single - valued Annotation):只有一个成员变量的注解。例如
@SuppressWarnings
,它用于抑制编译器警告,通常只需要指定抑制的警告类型。
@SuppressWarnings("unchecked")
public class UncheckedExample {
public void example() {
List list = new ArrayList();
list.add("string");
String s = (String) list.get(0);
}
}
- 完整注解(Full - fledged Annotation):包含多个成员变量的注解。开发者可以根据需求为不同的成员变量设置值。
Hibernate框架简介
Hibernate是一个开源的对象关系映射(Object Relational Mapping,ORM)框架,它使得Java开发者可以使用面向对象的方式操作数据库,而无需编写大量的SQL语句。Hibernate的核心功能包括:
- 对象关系映射:将Java对象与数据库表进行映射,使得可以通过操作Java对象来间接操作数据库中的数据。例如,一个Java类可以映射到数据库中的一张表,类的属性映射到表的列。
- 数据持久化:负责将Java对象的状态持久化到数据库中,以及从数据库中加载对象的状态。
- 事务管理:提供了对事务的支持,确保数据库操作的原子性、一致性、隔离性和持久性。
Java注解在Hibernate中的应用
实体类映射注解
@Entity
注解:用于将一个Java类声明为Hibernate中的实体类,这个类对应数据库中的一张表。
import javax.persistence.Entity;
@Entity
public class User {
// 类的属性和方法
}
@Table
注解:用于指定实体类对应的数据库表名。如果不使用@Table
注解,默认表名与类名相同。通过@Table
注解的name
属性可以指定表名,catalog
和schema
属性可以分别指定数据库目录和模式。
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "users", catalog = "my_db", schema = "public")
public class User {
// 类的属性和方法
}
@Id
注解:用于指定实体类中的哪个属性作为主键。主键是数据库表中唯一标识一条记录的字段。
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
private Long id;
// 其他属性和方法
}
@GeneratedValue
注解:与@Id
注解配合使用,用于指定主键的生成策略。常见的生成策略有IDENTITY
(自增长,适用于MySQL等数据库)、SEQUENCE
(序列,适用于Oracle等数据库)、AUTO
(由Hibernate根据数据库自动选择合适的策略)。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 其他属性和方法
}
@Column
注解:用于指定实体类属性对应的数据库表列的详细信息,如列名、长度、是否可为空等。
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", length = 50, nullable = false)
private String username;
@Column(name = "email", length = 100, unique = true)
private String email;
// 其他属性和方法
}
关系映射注解
- 一对一关系(One - to - One)
- 单向一对一:使用
@OneToOne
注解。例如,一个Person
实体类可能有一个唯一的Passport
实体类与之关联。
- 单向一对一:使用
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
private Passport passport;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Passport {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String number;
// 其他方法
}
- 双向一对一:除了
@OneToOne
注解,还需要在关联的两端设置mappedBy
属性来指定关系的维护端。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(mappedBy = "person")
private Passport passport;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Passport {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String number;
@OneToOne
private Person person;
// 其他方法
}
- 一对多关系(One - to - Many)
- 单向一对多:在“一”的一端使用
@OneToMany
注解,在“多”的一端使用@ManyToOne
注解。例如,一个Department
可能有多个Employee
。
- 单向一对多:在“一”的一端使用
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.List;
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
private List<Employee> employees;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
private Department department;
// 其他方法
}
- 双向一对多:在“一”的一端设置
mappedBy
属性指向“多”的一端维护关系的属性。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.List;
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department")
private List<Employee> employees;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
private Department department;
// 其他方法
}
- 多对多关系(Many - to - Many):使用
@ManyToMany
注解,并且通常需要一个中间表来维护关系。例如,Student
和Course
之间可能是多对多关系。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.List;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
private List<Course> courses;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.List;
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "courses")
private List<Student> students;
// 其他方法
}
继承映射注解
@Inheritance
注解:用于指定实体类继承体系的映射策略。常见的策略有JOINED
(每个子类对应一张表,通过外键关联到父类表)、SINGLE_TABLE
(所有子类和父类的数据存储在一张表中,通过一个鉴别器列区分不同的子类)、TABLE_PER_CLASS
(每个子类对应一张表,不共享父类表)。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Shape {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 其他方法
}
import javax.persistence.Entity;
@Entity
public class Circle extends Shape {
private double radius;
// 其他方法
}
import javax.persistence.Entity;
@Entity
public class Rectangle extends Shape {
private double width;
private double height;
// 其他方法
}
@DiscriminatorColumn
和@DiscriminatorValue
注解:当使用SINGLE_TABLE
策略时,@DiscriminatorColumn
用于指定鉴别器列的名称和类型,@DiscriminatorValue
用于指定子类在鉴别器列中的值。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "shape_type", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("shape")
public class Shape {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.DiscriminatorValue;
@Entity
@DiscriminatorValue("circle")
public class Circle extends Shape {
private double radius;
// 其他方法
}
import javax.persistence.Entity;
import javax.persistence.DiscriminatorValue;
@Entity
@DiscriminatorValue("rectangle")
public class Rectangle extends Shape {
private double width;
private double height;
// 其他方法
}
其他注解
@Transient
注解:用于指定一个属性不会被持久化到数据库中。例如,一个计算属性可能不需要存储在数据库中。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@Transient
private double discountedPrice;
// 其他方法
}
@Lob
注解:用于表示大对象类型,如Blob
(二进制大对象)或Clob
(字符大对象)。通常与@Column
注解配合使用,指定列的类型。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Column;
@Entity
public class Document {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@Lob
@Column(columnDefinition = "BLOB")
private byte[] content;
// 其他方法
}
@NamedQuery
和@NamedNativeQuery
注解:@NamedQuery
用于定义命名的JPQL(Java Persistence Query Language)查询,@NamedNativeQuery
用于定义命名的原生SQL查询。这些查询可以在整个应用程序中复用。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
@Entity
@NamedQuery(name = "User.findByUsername", query = "SELECT u FROM User u WHERE u.username = :username")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// 其他方法
}
在使用时,可以通过EntityManager
来执行这些命名查询:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.List;
public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my_persistence_unit");
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("User.findByUsername");
query.setParameter("username", "testUser");
List<User> users = query.getResultList();
em.close();
emf.close();
}
}
同样,@NamedNativeQuery
的使用方式类似,只是查询语句是原生SQL。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
@Entity
@NamedNativeQuery(name = "User.findByUsernameNative", query = "SELECT * FROM users WHERE username = :username", resultClass = User.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// 其他方法
}
然后可以通过EntityManager
执行原生SQL命名查询:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.List;
public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my_persistence_unit");
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("User.findByUsernameNative");
query.setParameter("username", "testUser");
List<User> users = query.getResultList();
em.close();
emf.close();
}
}
通过上述对Java注解在Hibernate中应用的详细介绍,可以看到注解在简化Hibernate配置、实现对象关系映射等方面发挥了重要作用,使得开发者能够更高效地使用Hibernate框架进行数据库相关的开发工作。