I'm migrating from Spring Boot 2.7 to Spring Boot 3.3.13. This means that I'm migrating even from Hibernate 5 to Hibernate 6. I'm having an annoying problem when I start my Spring Application about the configuration of my database configuration classes.
This is my one of my database configuration classes that i had on Spring Boot 2.7 (I censored package sensible names):
package ***.datasource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import jakarta.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
/**
* <p>
* Data source configuration for Anag Database.
*
*/
@Configuration
@ConditionalOnProperty(prefix = "spring.anag.datasource", name = "url")
public class AnagSourceConfiguration {
@Value("${spring.anag.hibernate.hbm2ddl.auto:validate}")
private String hibernateHbm2ddlAuto;
@Value("${hibernate.dialect}")
private String hibernateDialect;
@Bean(name = "anagDataSource")
@ConfigurationProperties("spring.anag.datasource")
public DataSource anagDataSource() {return DataSourceBuilder.create().build();
}
@Bean(name = "anagEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean anagEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(anagDataSource());
em.setPackagesToScan("***.entity.anag");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
final HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
properties.put("hibernate.dialect", hibernateDialect);
em.setJpaPropertyMap(properties);
return em;
}
@Bean(name = "anagTransactionManager")
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory anagEntityManagerFactory) {
return new JpaTransactionManager(anagEntityManagerFactory);
}
}
I manage to update something for the migration: I replaced every javax use with jakarta excluding the DataSource class since it seems a jakarta counterpart doesen't exists. Then, I added the Hibernate dialect on the properties and I replaced "jdbc-url" with "url" on ConditionalProperty name. Did same on yaml file of course.
Then, this is my repositories configuration class:
package ***.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@EnableJpaRepositories(
basePackages = "***.repositories.anag",
entityManagerFactoryRef = "anagEntityManagerFactory",
transactionManagerRef = "anagTransactionManager"
)
public class AnagRepositoriesConfig {
}
I dont think I have to change something here.
Now, I'm having this error when I start my application:
Error creating bean with name 'delegatorFilter' defined in file [C:\\Users\\***\\config\\DelegatorFilter.class]: Unsatisfied dependency expressed through constructor parameter 2: Error creating bean with name 'userDelegationService' defined in file [C:\\**\\service\\UserDelegationService.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'userAccountDelegationRepository' defined in **.repositories.anag.UserAccountDelegationRepository defined in @EnableJpaRepositories declared on AnagRepositoriesConfig: Cannot resolve reference to bean 'jpaSharedEM_anagEntityManagerFactory' while setting bean property
Parameter 0 of constructor in **.service.UserDelegationService required a bean named 'anagEntityManagerFactory' that could not be found.\r\n\r\n\r\nAction:\r\n\r\nConsider defining a bean named 'anagEntityManagerFactory' in your configuration
This part is pretty strange: Cannot resolve reference to bean 'jpaSharedEM_anagEntityManagerFactory. It seems a strange concatenation name with jpaSharedEm_ and my bean anagEntityManagerFactory. Why Spring search this bean name? I have to change some name configuration?
I don't think the problem depends from my UserAccountDelegationRepository. This is just the first repository that Spring met when the application starts. I changed the order declaration of repositories on the service and I meet this problem even for other repositories.
Someone met this problem? I see here there are some question about this same problem but I didn't find any relevant answer. I did all the best practices to migrate to Spring Boot 3. There are no more javax on code and I even removed every dependency. Can someone help me?
This is my yaml config about anag datasource:
spring:
anag:
datasource:
url: "jdbc:mysql://xxxxxxxx:3306/anag?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&tinyInt1isBit=false&useSSL=false"
driver-class-name: com.mysql.cj.jdbc.Driver
username: xxxxxxxx
password: xxxxxxxx
hibernate:
hbm2ddl:
auto: validate
-
Did you try to use ConditionalOnProperty instead of ConditionalProperty from import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; ?zawarudo– zawarudo2025年11月13日 02:41:18 +00:00Commented Nov 13 at 2:41
-
Yes sorry. I already wrote ConditionalOnProperty . Just made a mess with copy paste here.Removed– Removed2025年11月13日 08:38:06 +00:00Commented Nov 13 at 8:38
-
Probably conflict with configs. Tried to exclude? @SpringBootApplication(exclude = { HibernateJpaAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class })Max– Max2025年11月13日 08:42:02 +00:00Commented Nov 13 at 8:42
-
Tried just now but i have same error. I tried a trick naming my bean jpaSharedEM_anagEntityManagerFactory but it didn't work.Removed– Removed2025年11月13日 08:54:13 +00:00Commented Nov 13 at 8:54
-
Do you have proper datasource.url property in .properties file?Max– Max2025年11月13日 09:22:27 +00:00Commented Nov 13 at 9:22
1 Answer 1
For information on using non-default Datasource settings, please refer to howto.data-access.configure-two-datasources
This is a proof-of-concept test.
application.yaml: removehibernate: hbm2ddl:AnagSourceConfiguration.java: The main changes are all in this file.AnagRepositoriesConfig.java: The file is not required.
Database - Docker
docker run \
--name my-mysql-temp \
-e MYSQL_ROOT_PASSWORD=Passw0rd! \
-e MYSQL_DATABASE=demodb \
-e MYSQL_USER=demouser \
-e MYSQL_PASSWORD=Passw0rd! \
-p 3306:3306 \
-d \
mysql:8.0.43-debian
Project Tree
demo-mysql-jpa_ST
├── pom.xml
├── README.txt
└── src
└── main
├── resources
│ └── application.yaml <-- Change
└── java
└── com
└── example
├── DemoApplication.java
├── config
│ └── AnagSourceConfiguration.java <-- Change
├── entity
│ └── anag
│ └── Student.java
├── repo
│ └── anag
│ └── StudentRepository.java
├── service
│ └── anag
│ └── StudentService.java
└── controller
└── anag
└── StudentController.java
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.7</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-mysql-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-mysql-jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yaml
- remove
hibernate: hbm2ddl:
spring:
application:
name: demo-mysql-jpa
datasource:
url: jdbc:mysql://localhost:3306/firstdb
username: firstuser
password: Passw0rd1
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
anag:
datasource:
url: jdbc:mysql://localhost:3306/demodb
driver-class-name: com.mysql.cj.jdbc.Driver
username: demouser
password: Passw0rd!
jpa:
hibernate:
ddl-auto: update
show-sql: true
DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
AnagSourceConfiguration.java
The main changes are all in this file.
package com.example.config;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
//@Configuration
//@ConditionalOnProperty(prefix = "spring.anag.datasource", name = "url")
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(
basePackages = "com.example.repo.anag",
entityManagerFactoryRef = "anagEntityManagerFactory",
transactionManagerRef = "anagTransactionManager"
)
public class AnagSourceConfiguration {
/*
@Value("${spring.anag.hibernate.hbm2ddl.auto:validate}")
private String hibernateHbm2ddlAuto;
@Value("${hibernate.dialect}")
private String hibernateDialect;
*/
/*
@Bean(name = "anagDataSource")
@ConfigurationProperties("spring.anag.datasource")
public DataSource anagDataSource() {return DataSourceBuilder.create().build();
}
*/
// 1- DataSourceProperties binding YAML
@Bean
@ConfigurationProperties("spring.anag.datasource")
public DataSourceProperties anagDataSourceProperties() {
return new DataSourceProperties();
}
// 2- create HikariDataSource
@Bean
@ConfigurationProperties("anag.datasource.configuration")
public HikariDataSource anagDataSource(
@Qualifier("anagDataSourceProperties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
/*
@Bean(name = "anagEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean anagEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(anagDataSource());
em.setPackagesToScan("com.example.entity.anag");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendoimport com.zaxxer.hikari.HikariDataSource;
final HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
properties.put("hibernate.dialect", hibernateDialect);
em.setJpaPropertyMap(properties);
return em;
}
*/
// 3- EntityManagerFactory binding DataSource + JPA properties
@Bean(name = "anagEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean anagEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("anagDataSource") DataSource anagDataSource) {
return builder
.dataSource(anagDataSource)
.packages("com.example.entity.anag") // entity package
.persistenceUnit("anag")
.build();
}
/*
@Bean(name = "anagTransactionManager")
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory anagEntityManagerFactory) {
return new JpaTransactionManager(anagEntityManagerFactory);
}
*/
// 4- TransactionManager
@Bean(name = "anagTransactionManager")
public PlatformTransactionManager anagTransactionManager(
@Qualifier("anagEntityManagerFactory") EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
The AnagRepositoriesConfig.java file is not required.
Student.java
package com.example.entity.anag;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(length = 100, nullable = false)
private String name;
@Column(name = "birth_date")
private LocalDate birthDate;
@Column(length = 100)
private String email;
@Column(length = 2)
private String grade;
@Column(name = "enrollment_date")
private LocalDate enrollmentDate;
}
StudentRepository.java
package com.example.repo.anag;
import com.example.entity.anag.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface StudentRepository extends JpaRepository<Student, Integer> {
List<Student> findByName(String name);
}
StudentService.java
package com.example.service.anag;
import com.example.entity.anag.Student;
import com.example.repo.anag.StudentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
@RequiredArgsConstructor
@Transactional(transactionManager = "anagTransactionManager")
public class StudentService {
private final StudentRepository repo;
public List<Student> listAll() {
return repo.findAll();
}
public Optional<Student> findById(Integer id) {
return repo.findById(id);
}
public List<Student> findByName(String name) {
return repo.findByName(name);
}
public Student create(Student student) {
return repo.save(student);
}
public Student update(Integer id, Student student) {
return repo.findById(id)
.map(s -> {
s.setName(student.getName());
s.setBirthDate(student.getBirthDate());
s.setEmail(student.getEmail());
s.setGrade(student.getGrade());
s.setEnrollmentDate(student.getEnrollmentDate());
return repo.save(s);
})
.orElseThrow(() -> new RuntimeException("Student ID not found: " + id));
}
public void delete(Integer id) {
repo.deleteById(id);
}
}
StudentController.java
package com.example.controller.anag;
import com.example.entity.anag.Student;
import com.example.service.anag.StudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/anag/students")
public class StudentController {
private final StudentService service;
@GetMapping
public List<Student> listAll() {
return service.listAll();
}
@GetMapping("/{id}")
public Student findById(@PathVariable Integer id) {
return service.findById(id).orElse(null);
}
@GetMapping("/name/{name}")
public List<Student> findByName(@PathVariable String name) {
return service.findByName(name);
}
// CREATE
@PostMapping
public Student create(@RequestBody Student student) {
return service.create(student);
}
// UPDATE
@PutMapping("/{id}")
public Student update(@PathVariable Integer id, @RequestBody Student student) {
return service.update(id, student);
}
// DELETE
@DeleteMapping("/{id}")
public void delete(@PathVariable Integer id) {
service.delete(id);
}
}
Build
mvn clean package
Run
java -jar target/app.jar
Test
Create
curl -X POST http://localhost:8080/api/anag/students \
-H "Content-Type: application/json" \
-d '{
"name": "Alice",
"birthDate": "2005年05月20日",
"email": "[email protected]",
"grade": "A",
"enrollmentDate": "2023年09月01日"
}'
List All
curl http://localhost:8080/api/anag/students
Update
curl -X PUT http://localhost:8080/api/anag/students/1 \
-H "Content-Type: application/json" \
-d '{
"name": "AliceUpdated",
"birthDate": "2005年05月20日",
"email": "[email protected]",
"grade": "A",
"enrollmentDate": "2023年09月01日"
}'
Read Id: 1
curl http://localhost:8080/api/anag/students/1
Read Name is AliceUpdated
curl http://localhost:8080/api/anag/students/name/AliceUpdated
Delete Id: 1
curl -X DELETE http://localhost:8080/api/anag/students/1