Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 3522

“Not a Managed Type” Exception in Spring Data JPA

$
0
0
Contact Us Featured

1. Overview

When using Spring Data JPA we may encounter issues during the bootstrap time. Some of the beans may not be created, causing the application not to start. While the actual stack trace may vary, generally, it looks like this:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerAdapter'
...
Caused by: java.lang.IllegalArgumentException: Not a managed type: ...OurEntity
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:583)
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:85)
...

The root cause is a “Not a managed type” exception. In this article, we’ll delve into the possible reasons for this exception and explore its solutions.

2. Missed @Entity Annotation

One possible reason for facing this exception is that we may forget to mark our entity using the @Entity annotation.

2.1. Reproducing the Issue

Let’s assume we have the following entity class:

public class EntityWithoutAnnotation {
    @Id
    private Long id;
}

We also have its Spring Data JPA repository:

public interface EntityWithoutAnnotationRepository
  extends JpaRepository<EntityWithoutAnnotation, Long> {
}

And finally, we have the application class that scans all the classes mentioned above:

@SpringBootApplication
public class EntityWithoutAnnotationApplication {
}

Let’s try to bootstrap the Spring context using this application:

@Test
void givenEntityWithoutAnnotationApplication_whenBootstrap_thenExpectedExceptionThrown() {
    Exception exception = assertThrows(Exception.class,
      () -> SpringApplication.run(EntityWithoutAnnotationApplication.class));
    assertThat(exception)
      .getRootCause()
      .hasMessageContaining("Not a managed type");
}

As expected, we encountered the “Not a managed type” exception related to our entity.

2.2. Fixing the Issue

Let’s add the @Entity annotation to the fixed version of our entity:

@Entity
public class EntityWithoutAnnotationFixed {
    @Id
    private Long id;
}

The application and repository classes remain the same. Let’s try to bootstrap the application again:

@Test
void givenEntityWithoutAnnotationApplicationFixed_whenBootstrap_thenRepositoryBeanShouldBePresentInContext() {
    ConfigurableApplicationContext context = run(EntityWithoutAnnotationFixedApplication.class);
    EntityWithoutAnnotationFixedRepository repository = context
      .getBean(EntityWithoutAnnotationFixedRepository.class);
    assertThat(repository).isNotNull();
}

We successfully retrieved the ConfigurableApplicationContext instance and obtained the repository instance from there.

3. Migration From javax.persistance to jakarta.persistance

We may face another case of this exception when migrating our application to Jakarta persistence API.

3.1. Reproducing the Issue

Let’s assume we have the next entity:

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class EntityWithJakartaAnnotation {
    @Id
    private Long id;
}

Here we started using the jakarta.persistence package, but we’re still using Spring Boot 2. We’ll create the repository and application classes similarly to how we created them in the previous section.

Now, let’s try to bootstrap the application:

@Test
void givenEntityWithJakartaAnnotationApplication_whenBootstrap_thenExpectedExceptionThrown() {
    Exception exception = assertThrows(Exception.class,
      () -> run(EntityWithJakartaAnnotationApplication.class));
    assertThat(exception)
      .getRootCause()
      .hasMessageContaining("Not a managed type");
}

We face the “Not a managed type” again. Our JPA entities scanner expects us to use javax.persistence.Entity annotation instead of jakarta.persistence.Entity.

3.2. Fixing the Issue

In this case, we have two potential solutions. We can migrate to Spring Boot 3 and Spring Data JPA starts using jakarta.persistence. Alternatively, we can continue using javax.persistence.Entity if we’re not ready for migration.

4. Missed or Misconfigured @EntityScan

Another common situation where we may encounter the “Not a managed type” exception is when our JPA entity scanner can’t find the entity in the expected path.

4.1. Reproducing the Issue

First, we create another entity:

package com.baeldung.spring.entity;
@Entity
public class CorrectEntity {
    @Id
    private Long id;
}

It has the @Entity annotation and is placed in the entity package. Now, let’s create a repository:

package com.baeldung.spring.repository;
public interface CorrectEntityRepository extends JpaRepository<CorrectEntity, Long> {
}

Our repository is placed in the repository package. Finally, we create an application class:

package com.baeldung.spring.app;
@SpringBootApplication
@EnableJpaRepositories(basePackages = "com.baeldung.spring.repository")
public class WrongEntityScanApplication {
}

It’s placed in the app package. By default, Spring Data looks at repositories under the main class package and its sub-packages. Because of that, we need to specify the base repository package using @EnableJpaRepositories.  Now, let’s try to bootstrap the application:

@Test
void givenWrongEntityScanApplication_whenBootstrap_thenExpectedExceptionThrown() {
    Exception exception = assertThrows(Exception.class,
      () -> run(WrongEntityScanApplication.class));
    assertThat(exception)
      .getRootCause()
      .hasMessageContaining("Not a managed type");
}

We face the “Not a managed type” exception again. The reason is that the logic for entity scan is the same as for repository scan. The packages under our app package were scanned, we didn’t find any entities there and got the exception during the CorrectEntityRepository construction.

4.2. Fixing the Issue

To fix the issue, we can use the @EntityScan annotation.

Let’s create another application class:

@SpringBootApplication
@EnableJpaRepositories(basePackages =
  "com.baeldung.spring.repository")
@EntityScan("com.baeldung.spring.entity")
public class WrongEntityScanFixedApplication {
}

Now we specify the repository package using the @EnableJpaRepositories annotation and the entity package using the @EntityScan annotation. Let’s see how it works:

@Test
void givenWrongEntityScanApplicationFixed_whenBootstrap_thenRepositoryBeanShouldBePresentInContext() {
    ConfigurableApplicationContext context = run(WrongEntityScanFixedApplication.class);
    CorrectEntityRepository repository = context
      .getBean(CorrectEntityRepository.class);
    assertThat(repository).isNotNull();
}

We successfully bootstrapped the application. We retrieved the CorrectEntityRepository from the context, which means it was built and CorrectEntity was successfully recognized as a JPA Entity.

5. Conclusion

In this tutorial, we’ve explored why we might encounter the “Not a managed type” exception when using Spring Data JPA. We’ve also learned solutions to avoid it. The solution choice depends on the particular case, but understanding the possible reasons help us recognize the exact variant we’re facing.

As usual, the full source code can be found over on GitHub.

       

Viewing all articles
Browse latest Browse all 3522

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>