Spring Boot - Entity Scan

Spring Boot application automatically recognizes all the entities that are in the same package or its child packages, but issues build failure for entities defined in all other packages.

In order to avoid that, we can use @EntityScan which can be used to define all the packages that we need our application to scan for entities.

Let's assume the project structure mentioned below to understand how @EntityScan makes a difference.

Project Structure

com.randomcodez.app
    Application.java
    UserEntity.java
    CategoryEntity.java
com.randomcodez.app.controller
com.randomcodez.app.entity
    Article.java
    Question.java
com.randomcodez.app.repository
com.randomcodez.app.service
com.randomcodez.common.entity
    Topic.java
    Tutorial.java

Application.java - without @EntityScan

The basic Spring Boot application is defined as below without using @EntityScan.

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

When the Spring Boot application is defined without @EntityScan, then by default the application

  • will recognize all the entities defined in the same package com.randomcodez.app as it is inside the same package
    • so, no build issues in using the entities UserEntity.java and CategoryEntity.java
    • however, we avoid defining entities within the same package
  • will recognize all the entities defined in the package com.randomcodez.app.entity as it is inside one of its child packages
    • so, no build issues in using the entities Article.java and Question.java
    • we encourage defining entities in a separate package like these entities
  • will not recognize the entities defined in the package com.randomcodez.common.entity as it is not one of its child packages
    • so, the build will fail when we use the entities Topic.java and Tutorial.java
    • this can be resolved by defining EntityScan

When we try to use an entity class that is available but not part of the packages scanned for entities, the application build fails with the below error message that says the entity is not a managed type.

Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.randomcodez.commons.entity.Topic
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:582) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:85) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:75) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:228) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:178) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:161) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:72) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:319) ~[spring-data-commons-2.5.4.jar:2.5.4]
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:323) ~[spring-data-commons-2.5.4.jar:2.5.4]
	at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.5.4.jar:2.5.4]
	at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.5.4.jar:2.5.4]
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:329) ~[spring-data-commons-2.5.4.jar:2.5.4]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144) ~[spring-data-jpa-2.5.4.jar:2.5.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.9.jar:5.3.9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.9.jar:5.3.9]
	... 30 common frames omitted

Application.java - With @EntityScan

The basic Spring Boot application using @EntityScan is as below.

Entity Scan can include multiple packages with a comma between them as shown, which scans all the included packages for entities.

@SpringBootApplication
@EntityScan({"com.randomcodez.commons.entity", "com.randomcodez.app.entity", "com.randomcodez.app"})
public class Application extends SpringBootServletInitializer {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

Overall

Spring Boot application with @EnableScan helps us define all the entity packages, which need to be scanned and make available for the application.