如何解决具有单表继承的JPA存储库休眠
我创建了两个扩展RegularEmployee
实体的实体(ContactEntity
和Employee
)。
@Entity
@Table(name="employees")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type",discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(value="employee")
public class Employee {
@Id
@GeneratedValue
private Long id;
private String name;
...
我为此实现使用SINGLE_TABLE
继承,并创建了用于处理数据的通用JpaRepository:
@Repository
public interface EmployeeRepository<T extends Employee> extends JpaRepository<T,Long> {
}
我还创建了Service类,该类自动关联这些通用存储库的三个实例以及每个类的特定方法。
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository<Employee> employeeRepo;
@Autowired
private EmployeeRepository<RegularEmployee> regularRepo;
@Autowired
private EmployeeRepository<ContractEmployee> contractRepo;
public List<Employee> getAllEmployee() {
return employeeRepo.findAll();
}
public List<RegularEmployee> getAllRegularEmployee(){
return regularRepo.findAll();
}
public List<ContractEmployee> getAllContractEmployee() {
return contractRepo.findAll();
}
...
我的问题是,当我试图找到所有正式雇员或合同雇员时,我总是得到所有类型的雇员(雇员,正式雇员和合同雇员在一起)。
即使方法的签名表明它返回了适当的类型,我也不知道为什么会这样表现。
解决方法
我已经可以使用通用EmployeeRepository复制您遇到的情况。或者,我创建了两个单独的存储库:ContractualEmployeeRepository和RegularEmployeeRepository。
public interface ContractualEmployeeRepository extends JpaRepository<ContractualEmployee,String> {
}
public interface RegularEmployeeRepository extends JpaRepository<RegularEmployee,String> {
}
然后,我创建了一个集成测试。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Main.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,TransactionalTestExecutionListener.class,DbUnitTestExecutionListener.class})
@TestPropertySource(locations="classpath:application-test.properties")
@DatabaseSetup("classpath:SingleTableDataSet.xml")
public class IntegrationTest {
@Autowired
private RegularEmployeeRepository regularEmployeeRepository;
@Autowired
private ContractualEmployeeRepository contractualEmployeeRepository;
@Test
public void test() {
Assert.assertEquals(6,regularEmployeeRepository.findAll().size());
Assert.assertEquals(4,contractualEmployeeRepository.findAll().size());
}
}
它有效。
关于Spring Data JPA存储库中泛型的用法和局限性:https://stackoverflow.com/a/19443031/14180014他在解释它方面做得很出色。
,一种选择是在@Query
中使用EmployeeRepository
:
public interface EmployeeRepository<T extends Employee> extends JpaRepository<T,Long> {
@Query("from RegularEmployee")
List<RegularEmployee> findAllRegularEmployees();
}
第二个选项是为Employee
的每个子类创建一个附加存储库。对于RegularEmployee
将是:
public interface RegularEmployeeRepository extends EmployeeRepository<RegularEmployee>{}
这是在EmployeeService
中同时使用两个选项的方法:
@Service
public class EmployeeService {
@Autowired EmployeeRepository<Employee> employeeRepo;
@Autowired EmployeeRepository<RegularEmployee> regularRepoT;
@Autowired RegularEmployeeRepository regularRepo;
@PostConstruct
public void init(){
employeeRepo.save(new ContractEmployee("Mark"));
employeeRepo.save(new RegularEmployee("Luke"));
employeeRepo.findAll().forEach(System.out::println); // prints Mark and Luke
regularRepo.findAll().forEach(System.out::println); // prints only Luke
regularRepoT.findAllRegularEmployees().forEach(System.out::println); // prints only Luke
}
//...
}
您还可以在@Repository
上方省略EmployeeRepository
。 Spring已经知道这是一个存储库,因为它扩展了JpaRepository
。
旁注:如果您不需要由Spring创建EmployeeRepository
,请在其类的顶部添加@NoRepositoryBean
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。