5

I have this object:

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

..
}

and this one:

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

and this:

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

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

and

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

}

but when I do

Enfant enfant = enfantRepo.findOne(7L);

I have this error:

 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)

I also tried enfantRepo.findById with the same result

Nuñito Calzada
  • 4,394
  • 47
  • 174
  • 301
  • How did you persist your instance in the database? The error is indicating the row in the database is for a Personne instance, not an Enfant subclass instance, so you likely made a mistake in how you setup the data, not in how you are reading it - though you might want to check the PersonneClassExtractor class that it knows about subclasses and is interpreting the row correctly as a Enfant. – Chris Aug 31 '21 at 19:34
  • Do you have spring-boot-devtools in your classpath? – Ravi Parekh Sep 02 '21 at 13:57
  • your entities are in src or in dependency jar?(Which I faced). See Holger comment - https://stackoverflow.com/questions/54536895/cannot-be-cast-to-class-because-they-are-in-unnamed-module-of-loader-app – Ravi Parekh Sep 02 '21 at 14:35

2 Answers2

1

The findOne method provided by JpaSpecificationExecutor contract and the implementation underneath (`SimpleJpaRepository) has seen some changes in different spring-data-jpa project versions.

While this is not clear given the reported error, but the runtime may be generating a new query on-fly that does not match your polymorphic structure (you can activate hibernate SQL logging to inspect these).

That being said, you are better off using the findById and getById ready alternatives instead of creating your own query-based method. You should remove your custom findOne method out of your JpaRepository declaration:

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

    // ...
}

You are then able to query the Enfant entity based on its identifier:

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

Or simply bypassing the Optional return value using the getById alternative:

Enfant enfant = enfantRepo.getById(7L);
tmarwen
  • 15,750
  • 5
  • 43
  • 62
1

Your error might be misleading, according to this stackoverflow unless you are explicitly casting in your code.

And not sure both are in same jar|library in your code (depends on your structure)!! ERROR: in unnamed module of loader

Try, This may help if devtools is in your classpath.

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

OR

Exclude | Remove

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>
Ravi Parekh
  • 5,253
  • 9
  • 46
  • 58
  • I faced same issue but it was from different dependency `the unnamed module of loader 'app'`` AND https://stackoverflow.com/questions/61615491/tomcat-classcastexception-due-to-classloaders – Ravi Parekh Sep 02 '21 at 14:18