@Embeddable注解
一般和@Embedded搭配使用
@Embeddable是Hibernate中的注解之一,它的作用是标识一个类是可以嵌入(Embeddable)到其他实体类中的类。使用@Embeddable注解的类通常表示了一组相关的属性,这些属性可以被嵌入到其他实体中,而不需要创建独立的数据库表。主要特点和作用包括
可嵌入性(Embeddable)
被@Embeddable注解标识的类可以被嵌入到其他实体类中,它的属性将会被合并到包含它的实体类的表中,而不是创建一个独立的表。
代码重用
可以通过@Embeddable注解,将一组相关的属性定义在一个独立的类中,然后在多个实体类中重用这个类,提高了代码的重用性和可维护性。下面是一个简单的示例,演示了@Embeddable的基本用法
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
// Constructors, getters, setters, etc.
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Embedded
private Address address;
// Constructors, getters, setters, etc.
}
在这个例子中,Address类被@Embeddable注解标识,表示它可以被嵌入到其他实体类中。Employee实体类使用了@Embedded注解,将Address类嵌入到自身,从而共享Address中的属性。在数据库中,Employee表将包含street、city、zipCode等Address类的属性。总的来说,@Embeddable注解是为了支持实体类的组合,允许将一组属性定义在一个独立的类中,以提高代码的模块化和可读性。
复合查询
在使用@Embedded注解后,HQL(Hibernate Query Language)中的复合查询可以通过使用嵌入对象的属性路径来实现。嵌入对象的属性路径形式为embeddedObject.property。以下是一个示例,演示如何在HQL中进行复合查询
假设有一个实体类Employee,其中包含一个嵌入对象Address
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Embedded
private Address address;
// Constructors, getters, setters, etc.
}
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
// Constructors, getters, setters, etc.
}
如果我们想通过HQL查询Employee中特定地址的员工,可以使用以下查询
String hql = "FROM Employee e WHERE e.address.city = :city";
List employees = entityManager.createQuery(hql, Employee.class)
.setParameter("city", "SomeCity")
.getResultList();
在这个例子中,HQL查询中使用了嵌入对象的属性路径 e.address.city 来查询Employee中地址为特定城市的员工。注意事项
@Embeddable注解和@Embedded的实现原理
@Embeddable 和 @Embedded 是 Hibernate 中用于实体映射中的嵌入对象的注解。它们的实现原理涉及到 JPA(Java Persistence API)规范和 Hibernate 的实现。
@Embeddable 注解
- 作用@Embeddable 注解用于标识一个类是可嵌入的,可以作为其他实体的一部分。
- 实现原理 当一个类被标记为 @Embeddable 时,它告诉 Hibernate 这个类的实例可以被嵌入到其他实体中,不需要独立生成数据库表,而是被包含在包含它的实体的表中。
@Embedded 注解
- 作用@Embedded 注解用于标识一个字段或属性是一个嵌入对象。
- 实现原理 当一个字段或属性被标记为 @Embedded 时,它告诉 Hibernate 在数据库表中使用嵌入对象对应的列,而不是为该字段创建独立的表。这个注解通常与 @Embeddable 结合使用,将一个可嵌入的对象嵌入到另一个实体中。
实例
下面是一个简单的示例,演示了 @Embeddable 和 @Embedded 的用法
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
// Constructors, getters, setters, etc.
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Embedded
private Address address;
// Constructors, getters, setters, etc.
}
在这个例子中,Address 类被标记为 @Embeddable,表示它是一个可嵌入的类。Employee 实体中的 address 属性使用了 @Embedded 注解,将 Address 类嵌入到 Employee 实体中。这样,在数据库中 Employee 表会包含 street、city、zipCode 等属性的列,而不会单独生成一个 Address 表。实际的实现原理涉及到 JPA 提供商的具体实现,而 Hibernate 作为 JPA 的一个实现,会根据 JPA 规范来处理 @Embeddable 和 @Embedded 注解。在处理时,Hibernate 会动态生成适应于数据库的 SQL 语句,将嵌入对象的属性映射到包含它的实体的表中。
可嵌入实体的使用场景
给主实体增加字段
可嵌入实体常用于向主实体(包含嵌入实体的实体)增加一组字段,将这组字段抽象为一个独立的实体类。这样做有助于代码的模块化和重用。例如,假设有一个 Person 实体,可以使用嵌入实体 Address 来添加地址信息
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
// Constructors, getters, setters, etc.
}
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Embedded
private Address address;
// Constructors, getters, setters, etc.
}
给主实体增加级联关系
可嵌入实体还可以用于给主实体增加级联关系。嵌入实体可以包含与其他实体的关联关系,从而使得主实体也拥有这些关联关系。例如,假设有一个 Company 实体,可以使用嵌入实体 ContactInfo 来添加联系信息,其中的 ContactInfo 包含了与 Employee 实体的一对多关系
@Embeddable
public class ContactInfo {
@OneToMany(mappedBy = "company")
private List employees;
// Constructors, getters, setters, etc.
}
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String companyName;
@Embedded
private ContactInfo contactInfo;
// Constructors, getters, setters, etc.
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String employeeName;
@ManyToOne
private Company company;
// Constructors, getters, setters, etc.
}
在这个例子中,Company 实体通过嵌入实体 ContactInfo 拥有了与 Employee 实体的一对多关系。总体而言,可嵌入实体的使用场景包括但不限于给主实体增加字段、给主实体增加级联关系,通过将一组相关的字段或关联关系抽象成可嵌入实体,提高了代码的模块化和可读性。