【问题标题】:Hibernate Inheritance Mapping with SpringBoot - cast class Exception使用 SpringBoot 进行 Hibernate 继承映射 - 强制转换类异常
【发布时间】:2021-10-24 15:34:04
【问题描述】:

我有这个对象:

@Entity
@Table(name = "PERSONNE")
@NamedQuery(name = "Personne.findAll", query = "SELECT p FROM Personne p")
@Inheritance(strategy = InheritanceType.JOINED)
@ClassExtractor(PersonneClassExtractor.class)
@NoArgsConstructor
@AllArgsConstructor
@Data
@SuperBuilder
@ToString(of = { "personneId", "perId" })
@EqualsAndHashCode(of = { "personneId", "perId" })
public class Personne  implements  Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @ReturnInsert    
    @Column(name = "PERSONNE_ID")
    protected Long personneId;

..
}

还有这个:

@Entity
@Table(name = "ENFANT")
@NamedQuery(name = "Enfant.findAll", query = "SELECT e FROM Enfant e")
@PrimaryKeyJoinColumn(name = "PERSONNE_ID")
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@SuperBuilder
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Audit
public class Enfant extends Personne {

    private static final long serialVersionUID = 1L;
..
}

还有这个:

@Repository
public interface EnfantRepository extends PersonneBaseRepository<Enfant>,
        JpaSpecificationExecutor<Enfant> {

    @Query("SELECT e FROM Enfant e WHERE e.personneId = ?1")
    Enfant findOne(Long enfantId);
..
}

@NoRepositoryBean
public interface PersonneBaseRepository<T extends Personne> 
        extends JpaRepository<T, Long> {

}

但是当我这样做时

Enfant enfant = enfantRepo.findOne(7L);

我有这个错误:

 class com.mundos.model.persons.Personne cannot be cast to class com.mundos.model.persons.Enfant (com.mundos.model.persons.Personne and com.mundos.model.persons.Enfant are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @67cae0fe)

我也试过enfantRepo.findById,结果相同

【问题讨论】:

  • 你是如何将你的实例持久化到数据库中的?该错误表明数据库中的行是 Personne 实例,而不是 Enfant 子类实例,因此您可能在设置数据的方式上犯了错误,而不是在读取数据的方式上 - 尽管您可能想要检查 PersonneClassExtractor它知道子类并将该行正确解释为 Enfant 的类。
  • 你的类路径中有 spring-boot-devtools 吗?
  • 您的实体在 src 或依赖 jar 中?(我遇到过)。请参阅 Holger 评论 - stackoverflow.com/questions/54536895/…

标签: java spring-boot hibernate jpa spring-data-jpa


【解决方案1】:

JpaSpecificationExecutor 合约提供的findOne 方法及其底层实现(`SimpleJpaRepository)在不同的spring-data-jpa 项目版本中发生了一些变化。

虽然鉴于报告的错误尚不清楚,但运行时可能会即时生成与您的多态结构不匹配的新查询(您可以激活 hibernate SQL 日志记录来检查这些) .

话虽如此,您最好使用findByIdgetById 准备好的替代方案,而不是创建自己的基于查询的方法。您应该从您的 JpaRepository 声明中删除您的自定义 findOne 方法:

@Repository
public interface EnfantRepository extends PersonneBaseRepository<Enfant>, JpaSpecificationExecutor<Enfant> {

    // ...
}

然后您可以根据其标识符查询Enfant 实体:

Enfant enfant = enfantRepo.findById(7L).orElseThrow(() -> new EntityNotFoundException(id));

或者只是使用getById 替代方法绕过Optional 返回值:

Enfant enfant = enfantRepo.getById(7L);

【讨论】:

    【解决方案2】:

    根据this stackoverflow,您的错误可能具有误导性,除非您在代码中显式转换。

    并且不确定两者是否在您的代码中的同一个 jar|库中(取决于您的结构)!! ERROR: in unnamed module of loader

    试试吧,如果 devtools 在您的类路径中,这可能会有所帮助。

    public static void main(final String[] args) {
        System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(Application.class, args);
    }
    

    排除 |删除

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
    </dependency>
    

    【讨论】:

    猜你喜欢
    • 2015-09-09
    • 1970-01-01
    • 2017-12-07
    • 2011-11-22
    • 2010-11-25
    • 2011-01-13
    • 2021-03-13
    • 2012-04-21
    • 1970-01-01
    相关资源
    最近更新 更多