我有抽象類員工
public abstract class Employee {
private int employeeId;
private String name;
}
我也有一個擴展兩個具體的類Employee,這是OfficeEmployee和HomeEmployee其當前為空。這是我的控制器:
@RestController
@RequestMapping("/api/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@PostMapping("/office")
public EmployeeResponse saveOfficeEmployee(@RequestBody OfficeEmployee request) {
return employeeService.save(request);
}
@PostMapping("/home")
public EmployeeResponse saveHomeEmployee(@RequestBody HomeEmployee request) {
return employeeService.save(request);
}
}
最后是 EmployeeService 類:
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public Employee save(Employee request) {
// here i think i should do something like this: Employee employee = new OfficeEmployee or
// Employee employee = new HomeEmployee();
Employee employee = employeeRepository.save(employee);
return employee;
}
}
如何確定我從POST請求中得到了什么員工?我處理這個問題錯了嗎?
uj5u.com熱心網友回復:
為什么你認為你需要確定任何事情?EmployeeRepository已經能夠很好地處理所有型別的Employees.
要使其正常作業,Employee必須是@Entity. 不過,它仍然可以是抽象的。
作為旁注,具有單獨端點 ( /home, /office)的替代方法是使用@JsonTypeInfo一種可用策略來確定Employee輸入資料的子型別。
uj5u.com熱心網友回復:
是的,抽象類物體是我用來在多個表中添加公共列的東西。例如,如果我想在許多表上添加 createdDate 和 updatedDate,我會在抽象物體類中定義這 2 列(例如,稱之為 BaseDateEntity),并在我想使用它的所有物體類中繼承它。還使用@MappedSuperclass 注釋基本物體類。但是存盤庫應該是每個特定的物體類。您不能為繼承抽象 Employee 物體的所有物體使用 1 個存盤庫,否則將在超類 baseentity(=Employee) 的所有子類物體(OfficeEmployee、HomeEmployee、XyzEmployee、..)上執行查詢,這可能就足夠了時。
您的物體代碼的粗略示例。
import java.persistence.MappedSuperclass;
@MappedSuperclass
public abstract class Employee { //body skipped for brevity}
有一個替代方案。在您的基本物體上使用 @Entity 和 @DiscriminatorColumn 。并在您的子物體上使用 @Entity & @DiscriminatorValue 。
@Entity
@DiscriminatorColumn
@Inheritance(strategy=InheritanceType.JOINED) //more explanation on this below
public abstract class Employee {//body skipped for brevity}
@Entity
@DiscriminatorValue("Officeemployee")
public class OfficeEmplyee extends Employee {}
您不能同時使用 MappedSuperclass 和 Entity。所以選擇一個。
存盤庫的粗略示例
public interface EmployeeRepository<T extends Employee> extends JpaRepository<T, Long>{}
public interface OfficeEmployeeRepository extends JpaRepository<OfficeEmployee,Long>{}
顯然我跳過了 HomeEmployee 的代碼示例,因為它與 OfficeEmployee 相同。
此外,如果您從不希望專門針對 OfficeEmployees 進行查詢,則您也不需要 OfficeEmployeeRepository。如果你總是查詢Employees的所有子類,那么你只需要EmployeeRepository。但是,在這種情況下,我認為您既需要 EmployeeRepository 用于一般員工查詢,也需要 OfficeRepository 和 HomeRepository 用于查詢特定型別的員工
為了進一步解釋 MappedSuperclass 方法和 DiscriminatorValue 方法之間的區別,您必須考慮 DB 中的表。
在您不想為父(抽象)物體物件創建另一個表的簡單情況下,使用 MappedSuperclass 要簡單得多。它只是將抽象父物體中描述的附加列映射(添加)到子物體上。在我通常的用例(createdDate,updadedDate 列)中,這是更好的方法,因為沒有理由為所有具有 createdDate&updatedDate 列的資料集構建表。(所有帖子、公告、評論、主題、重新回復、A2A 等的表格?毫無意義)
但是,在您的情況下,您可能希望保留一張包含各種員工的表格。在這種情況下,使用 discriminatorcolumn 和 discriminatorvalue 方法。這就是@Inheritance(strategy=) 注釋發揮作用的地方。
如果@Inheritance 不存在,則默認繼承策略為 SINGLE_TABLE。這是不言自明的imo。所有子類物體列也添加到這個超類(抽象物體)表中。它將創建一個巨大的 Employee 表。由于它不需要連接查詢,因此查詢更快更簡單。但不利的一面是該表很大,而且會有很多空值。(如果 OfficeWorker 有名為 'OfficeLocation' 的列而 HomeWorker 沒有,則每個 HomeWorker 行在巨大的 Employee 表中都有 OfficeLocation=null。)
我上面使用的是JOINED策略。也是不言自明的。制作一張所有Employee的表,一張所有OfficeWorker的表,一張所有HomeWorker的表。但在這種情況下,Employee 表只有公共列值(id、name、..什么不是)和型別(OfficeWorker vs HomeWorker),以及用于連接查詢到 OfficeWorker 表和 HomeWorker 表的外鍵。
最后一個選項是 TABLE_PER_CLASS。它不會生成所有員工的表。所以它與 MappedSuperclass 注釋相同,但只是更冗長。從來不推薦。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/379574.html
