利用@Embeddable實(shí)現(xiàn)實(shí)體和級聯(lián)關(guān)系的分開定義
@Embeddable注解
一般和@Embedded搭配使用
@Embeddable是Hibernate中的注解之一,它的作用是標(biāo)識一個(gè)類是可以嵌入(Embeddable)到其他實(shí)體類中的類。使用@Embeddable注解的類通常表示了一組相關(guān)的屬性,這些屬性可以被嵌入到其他實(shí)體中,而不需要?jiǎng)?chuàng)建獨(dú)立的數(shù)據(jù)庫表。主要特點(diǎn)和作用包括
可嵌入性(Embeddable)
被@Embeddable注解標(biāo)識的類可以被嵌入到其他實(shí)體類中,它的屬性將會被合并到包含它的實(shí)體類的表中,而不是創(chuàng)建一個(gè)獨(dú)立的表。
代碼重用
可以通過@Embeddable注解,將一組相關(guān)的屬性定義在一個(gè)獨(dú)立的類中,然后在多個(gè)實(shí)體類中重用這個(gè)類,提高了代碼的重用性和可維護(hù)性。下面是一個(gè)簡單的示例,演示了@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.
}
在這個(gè)例子中,Address類被@Embeddable注解標(biāo)識,表示它可以被嵌入到其他實(shí)體類中。Employee實(shí)體類使用了@Embedded注解,將Address類嵌入到自身,從而共享Address中的屬性。在數(shù)據(jù)庫中,Employee表將包含street、city、zipCode等Address類的屬性??偟膩碚f,@Embeddable注解是為了支持實(shí)體類的組合,允許將一組屬性定義在一個(gè)獨(dú)立的類中,以提高代碼的模塊化和可讀性。
復(fù)合查詢
在使用@Embedded注解后,HQL(Hibernate Query Language)中的復(fù)合查詢可以通過使用嵌入對象的屬性路徑來實(shí)現(xiàn)。嵌入對象的屬性路徑形式為embeddedObject.property。以下是一個(gè)示例,演示如何在HQL中進(jìn)行復(fù)合查詢
假設(shè)有一個(gè)實(shí)體類Employee,其中包含一個(gè)嵌入對象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<Employee> employees = entityManager.createQuery(hql, Employee.class)
.setParameter("city", "SomeCity")
.getResultList();
在這個(gè)例子中,HQL查詢中使用了嵌入對象的屬性路徑 e.address.city 來查詢Employee中地址為特定城市的員工。注意事項(xiàng)
- 使用@Embedded注解時(shí),嵌入對象的屬性在HQL查詢中需要使用屬性路徑。
- 在HQL中使用嵌入對象的屬性路徑時(shí),需要使用實(shí)體類的別名(在這個(gè)例子中是e)。
- 請根據(jù)實(shí)際情況調(diào)整查詢條件和屬性路徑,確保查詢的準(zhǔn)確性。
@Embeddable注解和@Embedded的實(shí)現(xiàn)原理
@Embeddable 和 @Embedded 是 Hibernate 中用于實(shí)體映射中的嵌入對象的注解。它們的實(shí)現(xiàn)原理涉及到 JPA(Java Persistence API)規(guī)范和 Hibernate 的實(shí)現(xiàn)。
@Embeddable 注解
- 作用@Embeddable 注解用于標(biāo)識一個(gè)類是可嵌入的,可以作為其他實(shí)體的一部分。
- 實(shí)現(xiàn)原理 當(dāng)一個(gè)類被標(biāo)記為 @Embeddable 時(shí),它告訴 Hibernate 這個(gè)類的實(shí)例可以被嵌入到其他實(shí)體中,不需要獨(dú)立生成數(shù)據(jù)庫表,而是被包含在包含它的實(shí)體的表中。
@Embedded 注解
- 作用@Embedded 注解用于標(biāo)識一個(gè)字段或?qū)傩允且粋€(gè)嵌入對象。
- 實(shí)現(xiàn)原理 當(dāng)一個(gè)字段或?qū)傩员粯?biāo)記為 @Embedded 時(shí),它告訴 Hibernate 在數(shù)據(jù)庫表中使用嵌入對象對應(yīng)的列,而不是為該字段創(chuàng)建獨(dú)立的表。這個(gè)注解通常與 @Embeddable 結(jié)合使用,將一個(gè)可嵌入的對象嵌入到另一個(gè)實(shí)體中。
實(shí)例
下面是一個(gè)簡單的示例,演示了 @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.
}
在這個(gè)例子中,Address 類被標(biāo)記為 @Embeddable,表示它是一個(gè)可嵌入的類。Employee 實(shí)體中的 address 屬性使用了 @Embedded 注解,將 Address 類嵌入到 Employee 實(shí)體中。這樣,在數(shù)據(jù)庫中 Employee 表會包含 street、city、zipCode 等屬性的列,而不會單獨(dú)生成一個(gè) Address 表。實(shí)際的實(shí)現(xiàn)原理涉及到 JPA 提供商的具體實(shí)現(xiàn),而 Hibernate 作為 JPA 的一個(gè)實(shí)現(xiàn),會根據(jù) JPA 規(guī)范來處理 @Embeddable 和 @Embedded 注解。在處理時(shí),Hibernate 會動(dòng)態(tài)生成適應(yīng)于數(shù)據(jù)庫的 SQL 語句,將嵌入對象的屬性映射到包含它的實(shí)體的表中。
可嵌入實(shí)體的使用場景
給主實(shí)體增加字段
可嵌入實(shí)體常用于向主實(shí)體(包含嵌入實(shí)體的實(shí)體)增加一組字段,將這組字段抽象為一個(gè)獨(dú)立的實(shí)體類。這樣做有助于代碼的模塊化和重用。例如,假設(shè)有一個(gè) Person 實(shí)體,可以使用嵌入實(shí)體 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.
}
給主實(shí)體增加級聯(lián)關(guān)系
可嵌入實(shí)體還可以用于給主實(shí)體增加級聯(lián)關(guān)系。嵌入實(shí)體可以包含與其他實(shí)體的關(guān)聯(lián)關(guān)系,從而使得主實(shí)體也擁有這些關(guān)聯(lián)關(guān)系。例如,假設(shè)有一個(gè) Company 實(shí)體,可以使用嵌入實(shí)體 ContactInfo 來添加聯(lián)系信息,其中的 ContactInfo 包含了與 Employee 實(shí)體的一對多關(guān)系
@Embeddable
public class ContactInfo {
@OneToMany(mappedBy = "company")
private List<Employee> 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.
}
在這個(gè)例子中,Company 實(shí)體通過嵌入實(shí)體 ContactInfo 擁有了與 Employee 實(shí)體的一對多關(guān)系??傮w而言,可嵌入實(shí)體的使用場景包括但不限于給主實(shí)體增加字段、給主實(shí)體增加級聯(lián)關(guān)系,通過將一組相關(guān)的字段或關(guān)聯(lián)關(guān)系抽象成可嵌入實(shí)體,提高了代碼的模塊化和可讀性。