Недавно я обновил свое приложение Spring Boot с версии 2.x до 3.1.0. В этом приложении мы используем Spring Data JPA с методами запроса JPA. После обновления приложение не запускается, а в журнале отладки указываются проблемы, связанные с необнаружением именованных запросов.
Один из методов репозитория, который работал нормально в Spring Boot 2.x, но теперь вызывает проблемы:
Код: Выделить всё
List findByTenantAndBusinessUnitIdAndWatchersContaining(@Param("tenant") Long tenant, @Param("businessUnitId") Long businessUnitId, @Param("watchers") String userId);
Код: Выделить всё
2024-03-16 22:02:26.804 [03-16 22:02:26 IST] DEBUG [main] mdc:{} NamedQuery.hasNamedQuery:118 - Did not find named query AlertConfigJpaEntity.findByTenantAndBusinessUnitIdAndWatchersContaining.count
2024-03-16 22:02:26.804 [03-16 22:02:26 IST] DEBUG [main] mdc:{} SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke:303 - Creating new EntityManager for shared EntityManager invocation
2024-03-16 22:02:26.805 [03-16 22:02:26 IST] DEBUG [main] mdc:{} NamedQuery.lookupFrom:138 - Looking up named query AlertConfigJpaEntity.findByTenantAndBusinessUnitIdAndSourceNameIgnoreCaseAndToolNameIgnoreCaseAndIsPublished
2024-03-16 22:02:26.806 [03-16 22:02:26 IST] DEBUG [main] mdc:{} JdbcResourceLocalTransactionCoordinatorImpl.markRollbackOnly:310 - JDBC transaction marked for rollback-only (exception provided for stack trace)
java.lang.Exception: exception just for purpose of providing stack trace
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:310)
at org.hibernate.internal.AbstractSharedSessionContract.buildNamedQuery(AbstractSharedSessionContract.java:1021)
at org.hibernate.internal.AbstractSharedSessionContract.createNamedQuery(AbstractSharedSessionContract.java:899)
at org.hibernate.internal.AbstractSharedSessionContract.createNamedQuery(AbstractSharedSessionContract.java:120)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:360)
at jdk.proxy2/jdk.proxy2.$Proxy252.createNamedQuery(Unknown Source)
at org.springframework.data.jpa.repository.query.NamedQuery.hasNamedQuery(NamedQuery.java:113)
at org.springframework.data.jpa.repository.query.NamedQuery.lookupFrom(NamedQuery.java:141)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:180)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:252)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:111)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:99)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:88)
at java.base/java.util.Optional.map(Optional.java:260)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.(QueryExecutorMethodInterceptor.java:88)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:357)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:279)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:245)
at org.springframework.data.util.Lazy.get(Lazy.java:114)
Код: Выделить всё
@Entity
@Getter
@Setter
@Table(name = "alert_config")
@NoArgsConstructor
@SuperBuilder
public class AlertConfigJpaEntity {
private static final long serialVersionUID = 1L;
@Column(name = "TENANT")
protected Long tenant;
@Column(name = "BUSINESS_UNIT_ID")
private Long businessUnitId;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "alert_config_watcher_id", joinColumns = @JoinColumn(name = "alert_config_id"))
@Column(name = "watcher_id")
@Builder.Default
private Set watcherId = new HashSet();
//removed other fields to make it small
}
Код: Выделить всё
@Configuration
@EnableJpaRepositories(
basePackages = "com.authserver",
transactionManagerRef = "transactionManager",
entityManagerFactoryRef = "entityManagerFactory",
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "^com\\.authserver\\.postgres.*")
)
@ConditionalOnProperty(value = "spring.datasource.default.enabled", havingValue = "true")
public class MysqlDataSourceConfig {
@Bean(name = "mysqlDataSourceProps")
@Primary
@ConfigurationProperties("spring.datasource.default")
public DataSourceProperties cardDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties("spring.datasource.default.hikari")
public DataSource cardDataSource(@Qualifier("mysqlDataSourceProps") DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
@Bean(name = "entityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(@Qualifier("dataSource") DataSource dataSource) {
Set entityClasses = scanEntities("com.authserver", "com.authserver.authserver.postgres");
LocalContainerEntityManagerFactoryBean entityManger = new LocalContainerEntityManagerFactoryBean();
entityManger.setDataSource(dataSource);
entityManger.setPersistenceUnitName("default");
entityManger.setJpaPropertyMap(getVendorProperties());
entityManger.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManger.setPackagesToScan(entityClasses.toArray(new String[0]));
return entityManger;
}
private Set scanEntities(String includePackage, String excludePackage) {
Reflections reflectionsInclude = new Reflections(new ConfigurationBuilder()
.forPackages(includePackage)
.addScanners(new TypeAnnotationsScanner()));
Set> excludedEntities = reflectionsExclude.getTypesAnnotatedWith(Entity.class, true);
includedEntities.removeAll(excludedEntities);
return includedEntities.stream()
.map(entity -> entity.getPackage().getName())
.collect(Collectors.toSet());
}
private Map getVendorProperties() {
Map properties = new HashMap();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
// properties.put("hibernate.session_factory.interceptor", queryInterceptor);
return properties;
}
@Bean(name = "transactionManager")
@Primary
public PlatformTransactionManager mysqlTransactionManager(@Qualifier("entityManagerFactory")
LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(mysqlEntityManagerFactory.getObject()));
}
}
Мы используем конфигурацию с несколькими источниками данных, и в качестве шага по устранению неполадок я попытался переключиться на автоматическую настройку Spring Boot, удалив конфигурацию с несколькими источниками данных, но проблема не устранена.
p>
Как решить эту проблему и гарантировать, что мои методы запросов JPA распознаются и выполняются должным образом в Spring Boot 3.1.0?
Подробнее здесь: https://stackoverflow.com/questions/781 ... ing-boot-3