java - Spring Data Repository Generics - 尝试获取错误的类型

标签 java spring generics spring-data-jpa spring-data

抽象练习实体:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Exercise {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;

}

抵抗运动实体:

@Entity
public class ResistanceExercise extends Exercise {
    ...
}

持续时间练习实体:

@Entity
public class DurationExercise extends Exercise {
    ...
}

抽象锻炼日志实体

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class ExerciseLog<T extends Exercise> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;

    @ManyToOne
    private T exercise;
}

抵抗运动日志实体:

@Entity
public class ResistanceExerciseLog extends ExerciseLog<ResistanceExercise> {

...

}

持续时间锻炼日志实体:

@Entity
public class DurationExerciseLog extends ExerciseLog<DurationExercise> {

    ... 
}

锻炼日志存储库:

public interface ExerciseLogRepository<T extends ExerciseLog<S>, S extends Exercise> extends JpaRepository<T, Long> {

}

Controller :

@RestController
@RequestMapping(value = "/api/v1/exercise-logs")
public class ExerciseLogController {

    @Autowired
    ExerciseLogRepository<ExerciseLog<Exercise>, Exercise> repository;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ResponseEntity<List<ExerciseLog<Exercise>>> getLogs() {

        Pageable pageable = PageRequest.of(0, 20, Sort.unsorted());

        Page<ExerciseLog<Exercise>> pageResult = repository.findAll(pageable);
        return ResponseEntity.ok().body(pageResult.getContent());
    }       
}

通过上述设置,并存储多种日志类型,当调用 Controller 的端点时,会抛出异常(完整堆栈跟踪 here ),代码如下:

javax.persistence.EntityNotFoundException: Unable to find uk.deepblue.personaltrainer.domain.exercise.ResistanceExercise with id 8
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:159) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1240) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1123) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:682) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.type.EntityType.resolve(EntityType.java:464) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:239) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]

没有id为8的ResistanceExercise,即DurationExercise,并且它仅从DurationExerciseLog表中引用,因此Spring/Hibernate似乎无法正确协商基础表。

我尝试了许多不同的配置,最终得到了相同的结果。看起来 TABLE_PER_CLASS 继承策略是我想要做的事情的最佳选择(例如 Using generics in Spring Data JPA repositories ),这是我当前的设置(如上所述)。

是否可以使用多态查询和泛型来做到这一点,或者我是否必须为我拥有的每个锻炼日志/锻炼组合进行调用?

最佳答案

感谢 Manish 的建议,添加 targetEntity=Exercise.class 解决了这个问题(尽管更改为 @MappedSuperclass 在这里并不合适,因为它会阻止在其他场景中的其他地方使用练习实体)

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class ExerciseLog<T extends Exercise> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;

    @ManyToOne(targetEntity=Exercise.class)
    private T exercise;
}

关于java - Spring Data Repository Generics - 尝试获取错误的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51875329/

相关文章:

Java 多态泛型调用

java - 从 HashMap 键获取路径 (Java)

java - Spring Boot + WEB-INF

Spring testcontainers Driver org.testcontainers.jdbc.ContainerDatabaseDriver 声称不接受 jdbcUrl

java - 编译器认为 Comparable 类型不是 Comparable

java - Java 中的泛型——实现接口(interface)

java - 在 Java 中的 JTable 中显示二维数组

java - Spring引导加载以数字为键的嵌套属性

java - spark 类型的 SparkJava Web get(string, Route) 不适用

java - 使用 Spring 和 Hessian 的互操作性?是否可以?