Spring Data JPA仓库中的继承问题

17
我有一个被注解为@MappedSuperClass的抽象类。大约有15个实体类继承自这个抽象类(在数据库中有15个对应的表)。这15个实体类都具有从抽象超类继承而来的相同属性。
我已经创建了以下用于抽象类的存储库:
@NoRepositoryBean
public interface AbstractRepository <T extends AbstractClass, E extends Serializable>
                                    extends PagingAndSortingRepository<T, Serializable> {
  .....some methods here
}

这15个实体/表储存了一些数据(与15个不同的设备有关的数据)。根据所选设备,将检索该表中的数据。我是否需要为15个具体实体创建15个单独的仓库,或者有没有办法仅使用抽象仓库获取特定设备的特定实体?如果需要为每个具体实体创建仓库,如何获取特定设备调用正确的仓库?(可能在应用程序启动时将表名和仓库类存储在一个映射中?)
2个回答

20
理想情况下,以下设置应该有效:
引用部分: 实体类
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Equipment { ... }

@Entity
public class Crane extends Equipment {}

@Entity
public class Excavator extends Equipment {}

Repository interface

public interface EquipmentRepository<T extends Equipment> extends CrudRepository<T> {}
代码库使用者
@Service
public class SomeService {
  @Autowired
  private EquipmentRepository<Crane> craneRepository;

  @Autowired
  private EquipmentRepository<Excavator> excavatorRepository;
}

我已经在Github上建立了一个样例项目以演示其功能。运行Maven测试作为以下任意一项都将显示通过测试,以证明设置按预期工作。

mvn test -Dspring.profiles.active="default,eclipselink"

mvn test -Dspring.profiles.active="default,openjpa"

话虽如此,这种设置可能与您使用的Hibernate不兼容。Hibernate不支持带有TABLE_PER_CLASS继承的自动递增标识符列。因此,尝试使用Hibernate运行上面的设置将会抛出异常。可以通过在上面链接的示例上运行以下内容来验证这一点。

mvn test -Dspring.profiles.active="default,hibernate"

16
您需要为每个类创建一个仓库(repository)。但是,您可以将方法放在抽象类中。您需要在每个方法上提供@Query,并使用SpeL(Spring 表达式语言)将类型添加到查询中。
@NoRepositoryBean
public interface AbstractRepository<T extends AbstractEquipment> 
        extends CrudRepository<T, Long>{

 @Query("select e from #{#entityName} as e from equipment where e.name = equipmentName")
 T findEquipmentByName(String equipmentName);

}

然后像下面这样扩展:
@Transactional
public interface SpecialEquipmentRepo extends AbstractRepository<SpecialEquipment,Long>{

}

感谢 @Joseph 的澄清。由于每个设备都需要创建存储库,那么获取特定设备的存储库实例的更好方法是什么?一种方法是自动装配所有15个存储库,并使用 switch case 根据传递的设备使用正确的存储库实例(类似于工厂返回正确的存储库)。 - Prateek Mehra
1
我建议避免使用switch语句,因为这需要维护。你可以使用@Autowire注解来自动装配一个Map,其中键是类型,值是存储库类型。 - Joseph McCarthy
“@NoRepositoryBean” 是处理仓库继承的关键提示,非常感谢! - Guillermo
谢谢。在编写SpeL查询时,如何加入其他表? - Robert Ngetich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接