我有一个用@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个单独的存储库,或者是否有任何方法可以仅使用抽象存储库来获取所选设备的特定实体?如果需要为每个具体实体创建存储库,如何为特定设备调用获取正确的存储库? (将表名和存储库类存储在可能在应用程序启动时创建的映射中?)
答案 0 :(得分:3)
理想情况下,以下设置应该有效:
实体类
@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"
答案 1 :(得分:2)
您必须为每个类创建存储库。但是,您可以将您的方法保持抽象。您需要在每个方法上提供@Query
并使用SpeL(Spring Expression Language)将类型添加到查询中。
@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>{
}