Spring Data JPA inheritance in repositories

前端 未结 2 357
抹茶落季
抹茶落季 2021-01-02 04:51

I have an abstract class annotated with @MappedSuperClass. There are around 15 entities that extend this abstract class (having 15 corresponding tables in the d

相关标签:
2条回答
  • 2021-01-02 05:09

    Ideally, the following set up should work:

    Entity classes

    @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> {}
    

    Repository consumer

    @Service
    public class SomeService {
      @Autowired
      private EquipmentRepository<Crane> craneRepository;
    
      @Autowired
      private EquipmentRepository<Excavator> excavatorRepository;
    }
    

    I have set up a sample project on Github to demonstrate this in action. Running Maven tests as any of the following will show passing tests to demonstrate that the set up works as expected.

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

    That said, this set up may not work with Hibernate, which is what I suspect you are using. Hibernate does not support auto-incremented identifier columns with TABLE_PER_CLASS inheritance. Therefore, attempting to run the set up above with Hibernate will throw an exception. This can be verified by running the following on the sample linked above.

    mvn test -Dspring.profiles.active="default,hibernate"
    
    0 讨论(0)
  • 2021-01-02 05:25

    You will have to create repository for each class. However you can keep your methods in the abstract. You'll need to provide @Query on each of the methods and use SpeL(Spring Expression Language) to add the type to the queries.

    @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);
    
    }
    

    Then extend like the following

    @Transactional
    public interface SpecialEquipmentRepo extends AbstractRepository<SpecialEquipment,Long>{
    
    }
    
    0 讨论(0)
提交回复
热议问题