All my attempts at classpath scanning of #Entity classes failed in a Spring boot application. The most common solution I found on the web was this and it didn't work -
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.acme.domain");
#EntityScan on a #Configuration class did not work either.
All the entities and their mappings were listed in orm.xml and I had to move back to using #Entity annotations.
One solution that got me half way there was -
<persistence-unit>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>META-INF/orm.xml</mapping-file>
<class>com.acme.domain.Entity</class>
<shared-cache-mode>NONE</shared-cache-mode>
</persistence-unit>
This way I could use the #Entity annotations if I listed entity classes in persistence.xml.
The solution I didn't find while searching, which is listed on Spring Data JPA web page is this -
ClasspathScanningPersistenceUnitPostProcessor postProcessor = new ClasspathScanningPersistenceUnitPostProcessor("com.acme.domain");
entityManagerFactory.setPersistenceUnitPostProcessors(postProcessor);
Now the classpath scanning of #Entity classes is enabled. No mappings in orm.xml and no listing of entities in persistence.xml.
Sharing your code will help troubleshoot. Is there a github project you can share?
One thing to keep in mind is that SpringBoot takes an "opiniated" approach to everything. This means that for JPA, there is a "boot" way of doing things. Spring Tool Suite is your friend here.
Recommend checking this tutorial that shows you how to do JPA in Boot. Also, when using boot, I strongly recommend to start with a maven project setup from the Spring Initializer project.
Related
I am working with spring batch. I needed to add some jpa repositories. So previously i was using JDBCTemplate which was working fine.
But when I started working with JPA, the spring boot application could not find the repos. Which were there.
#Autowired
ClassLevelConfigRepo clcr;
I checked these things as the best practices.
Added #EnableJpaRepositories in springBoot application class.
Added #Repostiories to the repository interfaces.
extended the interfaces with JpaRepository<Account, String>
Added #Entity to the entity classes and defined the #Table and # Column annotations properly.
But I am still getting below error.
Field clcr in com.cloudtask.batchconfig.util.LhmUtility required a bean of type 'com.cloudtask.batchconfig.repo.ClassLevelConfigRepo' that could not be found.
I tried checking all the dependencies in pom.xml it was as per recommended. And I have all the tables defined properly in data base.
I was expecting the application to return the Autowired clcr object propely.
Edit 1 : spring boot application annotations
#SpringBootApplication
#ComponentScan({"com.cloudtask"})
#EnableAsync
#IntegrationComponentScan({"com.cloudtask"})
#EnableIntegrationManagement(defaultLoggingEnabled = "true")
#EnableJpaRepositories
#EntityScan
public class imclassApplication ```
When you work with Spring Data Jpa with those basic points you should also keep track of below points.
you have added spring-boot-starter-data-jpa in your pom.xml
you have added the entity and repo package below one level of the application package.
If you the package is at same level you should specify the exact package details in the annotation. in your case it should be like :
#EnableJpaRepositories("com.cloudtask.batchconfig.repo")
#EntityScan(basePackages = {"com.cloudtask.batchconfig.entity"})
Happy programming!
I was going through this tutorial where the instructor was configuring Spring Data JPA. He had created the Entity classes and Repository interfaces and then added the #EnableJpaRepositories and #EntityScan annotations on the main application as follows:
#SpringBootApplication
#ComponentScan({"com.test.controller", "com.test.services"})
#EnableJpaRepositories("com.test.repository")
#EntityScan("com.test.entity")
public class MainApplication{
public static void main(String args[]){
SpringApplication.run(MainApplication.class, args[]);
}
}
I was creating the same project on the side, which had the same Entity classes and Repository interfaces but my main application didn't have these annotations. Instead, I added only #SpringBootApplication. Despite the absence of the said annotations, I found the code to be working well and fetching data from the db without issues. So my question is, what is the advantage of adding these annotations to the code ? Is it just for specifying the package where you can find the corresponding files, or are there any other advantages ?
By default, Spring searches for entities and repos in package where you placed your main class (and below this package). For example having these packages:
java
-com
---pack1
-----AnyEntity.java
---pack2
-----Main.java
Spring won't be able to find AnyEntity automatically. In this situation you need to specify where the entity is using #EntityScan. When it comes to repositories, you deal with it similarly using #EnableJpaRepositories.
I'm working on a Spring Boot Rest project with 500~ entity in it. But it is slow on start up duration (about 3 minutes) because of the EntityManagerFactory initialization. And it has 5GB~ memory allocation.
Using profiles I want to open a lightweighted version of my project. I'm trying to avoid some of the entities to be mapped via EntityManagerFactory. And related beans via ComponentScan.
Do you have any solution related this issue?
For example I wanna hide some of the packages from hibernate & spring boot auto configuration.
If the class path scanning takes to long you can narrow it down to specific packages
#ComponentScan(basePackages = "com.your.project")
#EntityScan(basePackages = "com.your.project.model")
#EnableJpaRepositories(basePackages = "com.your.project.repository")
You also have an option to create a custom EntityManagerFactory as explained in this answer with a custom ConnectionProvider.
Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}
How do I configure hibernate?
If hibernate-entitymanager package is used for JPA then what good is of hibernate-jpa package. And I have seen that they use org.hibernate.ejb.HibernatePersistence class is used for JPA provider in persistence.xml which is in hibernate-entitymanager package.
In some cases, I have not seen the provider tag in persistence.xml. In this case which class is used?. Does Session class has EntityManager or implements it . And none of hibernate beans are specified in Spring-application context file directly. Instead spring.orm packages are used. So spring framework picks which class for JPA functionality.
org.springframework.orm.jpa.LocalEntityManagerFactoryBean picks which bean if provider tag is specified and if provider tag is not specified which bean is picked?
Hibernate JPA is a standard JPA implementation. See also these other questions about differences.
What's the difference between JPA and Hibernate?
Difference between Hibernate and Hibernate JPA
similarity and difference between jpa and hibernate
Session and EntityManager do approximately the same thing. EntityManager is the "new way."
I'm not clear on what your questions are about the persistence.xml file.
Thanks for reply but my Question was in which package the jpa implementation actually is . Is it in hibernate entitymanager.jar or hibernate-jpa2.1.jar . I found this fallowing link to be of little use
.https://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/ch01s02s01.html
but in this case in persistence.xml file contains org.hibernate.ejb.HibernatePersistence as jpa provider but this class is in hibernate-entitymanager package . But they also told that hibernate-jpa-2.0-api.jar is the JAR containing the JPA 2.0 API, it provides all the interfaces and concrete classes that the specification defines as public API. Said otherwise, you can use this JAR to bootstrap any JPA provider implementation. in this fallowing link
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html please could some one help me with this