弹簧数据库中的JPA继承
问题描述:
我有一个带有注释的抽象类@MappedSuperClass
。大约有15个实体扩展了这个抽象类(在数据库中有15个对应的表)。这15个实体都具有从抽象超类继承的相同属性。弹簧数据库中的JPA继承
我已经创建了一个库,如下为抽象类:
@NoRepositoryBean
public interface AbstractRepository <T extends AbstractClass, E extends Serializable>
extends PagingAndSortingRepository<T, Serializable> {
.....some methods here
}
的15个实体/表存储一些数据(与15个单独的设备的数据)。根据所选设备,将检索该表中的数据。我是否必须为15个具体实体创建15个独立的存储库,或者是否有任何方法可以仅使用抽象存储库获取选定设备的特定实体?如果需要为每个具体实体创建存储库,如何为特定设备调用获取正确的存储库? (将表名和存储库类存储在应用程序启动时创建的映射中)?
答
您必须为每个类创建存储库。但是,您可以保留抽象的方法。您需要在每种方法上提供@Query
,并使用SpeL(Spring表达式语言)将该类型添加到查询中。
@NoRepositoryBean
public interface AbstractRepository
extends CrudRepository<T extends AbstractEquipment,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>{
}
答
理想的情况下,以下设置应工作:
实体类
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Equipment { ... }
@Entity
public class Crane extends Equipment {}
@Entity
public class Excavator extends Equipment {}
库接口
public interface EquipmentRepository<T extends Equipment> extends CrudRepository<T> {}
库消费者
@Service
public class SomeService {
@Autowired
private EquipmentRepository<Crane> craneRepository;
@Autowired
private EquipmentRepository<Excavator> excavatorRepository;
}
我已成立了一个样本项目on 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"
感谢@约瑟夫的澄清。由于需要创建每个设备的存储库,因此为特定设备获取存储库实例的更好方法是什么?一种方法是自动装载所有15个存储库,并根据传递的设备使用正确的存储库实例(类似于工厂返回正确的存储库) –
我会避免使用交换机,因为必须维护交换机,你可以'@ Autowire'一个映射,其中键是类型,值是存储库类型。 –