如何从 Spring Boot 应用程序获取 ServiceRegistry 实例?
How to get ServiceRegistry instance from Spring Boot application?
我正在尝试使用 CommandLineRunner 访问底层 Hibernate 数据库的信息,以便我最终可以转储模式文件。我需要访问服务注册表实例才能执行此操作。
我尝试查看是否可以通过以下代码从 AutoWired EntityManagerFactory 获取它:
package test;
import javax.persistence.EntityManagerFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AutoWiredTest implements CommandLineRunner {
@Autowired
private EntityManagerFactory emf;
@Override
public void run(String... args)
throws Exception {
SessionFactoryImplementor sessionFactory = emf.unwrap(SessionFactoryImplementor.class);
ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry();
if( serviceRegistry == null )
throw new Exception("Service registry is null");
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
metadataSources.buildMetadata();
}
应用程序给我这个错误:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:780) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:761) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.4.jar:2.6.4]
at test.AutoWiredTest.main(AutoWiredTest.java:31) ~[classes/:na]
Caused by: org.hibernate.HibernateException: Unexpected type of ServiceRegistry [org.hibernate.service.internal.SessionFactoryServiceRegistryImpl] encountered in attempt to build MetadataBuilder
at org.hibernate.boot.internal.MetadataBuilderImpl.getStandardServiceRegistry(MetadataBuilderImpl.java:113) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.internal.MetadataBuilderImpl.<init>(MetadataBuilderImpl.java:93) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.MetadataSources.getMetadataBuilder(MetadataSources.java:146) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.MetadataSources.buildMetadata(MetadataSources.java:202) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at test.AutoWiredTest.run(AutoWiredTest.java:26) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) ~[spring-boot-2.6.4.jar:2.6.4]
... 5 common frames omitted
接下来,我尝试使用以下代码创建构建器:
package test;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BuilderTest implements CommandLineRunner {
@Override
public void run(String... args)
throws Exception {
new StandardServiceRegistryBuilder().configure().build();
}
public static void main(String[] args)
throws Exception {
SpringApplication.run(test.BuilderTest.class, args);
}
}
导致此错误的原因:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:780) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:761) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.4.jar:2.6.4]
at test.BuilderTest.main(BuilderTest.java:18) ~[classes/:na]
Caused by: org.hibernate.internal.util.config.ConfigurationException: Could not locate cfg.xml resource [hibernate.cfg.xml]
at org.hibernate.boot.cfgxml.internal.ConfigLoader.loadConfigXmlResource(ConfigLoader.java:53) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.registry.StandardServiceRegistryBuilder.configure(StandardServiceRegistryBuilder.java:254) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.registry.StandardServiceRegistryBuilder.configure(StandardServiceRegistryBuilder.java:243) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at test.BuilderTest.run(BuilderTest.java:13) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) ~[spring-boot-2.6.4.jar:2.6.4]
... 5 common frames omitted
它正在寻找 cfg.xml 文件,但我已经在 application.properties 文件中定义了我的数据库配置:
hibernate.current_session_context_class=thread
hibernate.format_sql=false
hibernate.show_sql=false
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/marketing
spring.datasource.username=marketing
spring.datasource.password=[PASS]
spring.logging.level.root=ERROR
spring.logging.level.org.hibernate=INFO
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDB103Dialect
知道出了什么问题吗?
似乎 Spring 只是没有将 Hibernate ServiceRegistry
注册为 bean。我查看了源代码,发现它的实例是在 SessionFactoryImpl
构造函数中创建的。
您可以尝试应用此 hack。
@SpringBootApplication
public class AutoWiredTest implements CommandLineRunner {
@Autowired
private EntityManagerFactory emf;
@Override
public void run(String... args)
throws Exception {
SessionFactoryImplementor sessionFactory = emf.unwrap(SessionFactoryImplementor.class);
ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry();
}
public static void main(String[] args)
throws Exception {
SpringApplication.run(AutoWiredTest.class, args);
}
}
我正在尝试使用 CommandLineRunner 访问底层 Hibernate 数据库的信息,以便我最终可以转储模式文件。我需要访问服务注册表实例才能执行此操作。
我尝试查看是否可以通过以下代码从 AutoWired EntityManagerFactory 获取它:
package test;
import javax.persistence.EntityManagerFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AutoWiredTest implements CommandLineRunner {
@Autowired
private EntityManagerFactory emf;
@Override
public void run(String... args)
throws Exception {
SessionFactoryImplementor sessionFactory = emf.unwrap(SessionFactoryImplementor.class);
ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry();
if( serviceRegistry == null )
throw new Exception("Service registry is null");
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
metadataSources.buildMetadata();
}
应用程序给我这个错误:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:780) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:761) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.4.jar:2.6.4]
at test.AutoWiredTest.main(AutoWiredTest.java:31) ~[classes/:na]
Caused by: org.hibernate.HibernateException: Unexpected type of ServiceRegistry [org.hibernate.service.internal.SessionFactoryServiceRegistryImpl] encountered in attempt to build MetadataBuilder
at org.hibernate.boot.internal.MetadataBuilderImpl.getStandardServiceRegistry(MetadataBuilderImpl.java:113) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.internal.MetadataBuilderImpl.<init>(MetadataBuilderImpl.java:93) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.MetadataSources.getMetadataBuilder(MetadataSources.java:146) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.MetadataSources.buildMetadata(MetadataSources.java:202) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at test.AutoWiredTest.run(AutoWiredTest.java:26) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) ~[spring-boot-2.6.4.jar:2.6.4]
... 5 common frames omitted
接下来,我尝试使用以下代码创建构建器:
package test;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BuilderTest implements CommandLineRunner {
@Override
public void run(String... args)
throws Exception {
new StandardServiceRegistryBuilder().configure().build();
}
public static void main(String[] args)
throws Exception {
SpringApplication.run(test.BuilderTest.class, args);
}
}
导致此错误的原因:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:780) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:761) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.4.jar:2.6.4]
at test.BuilderTest.main(BuilderTest.java:18) ~[classes/:na]
Caused by: org.hibernate.internal.util.config.ConfigurationException: Could not locate cfg.xml resource [hibernate.cfg.xml]
at org.hibernate.boot.cfgxml.internal.ConfigLoader.loadConfigXmlResource(ConfigLoader.java:53) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.registry.StandardServiceRegistryBuilder.configure(StandardServiceRegistryBuilder.java:254) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.registry.StandardServiceRegistryBuilder.configure(StandardServiceRegistryBuilder.java:243) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at test.BuilderTest.run(BuilderTest.java:13) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) ~[spring-boot-2.6.4.jar:2.6.4]
... 5 common frames omitted
它正在寻找 cfg.xml 文件,但我已经在 application.properties 文件中定义了我的数据库配置:
hibernate.current_session_context_class=thread
hibernate.format_sql=false
hibernate.show_sql=false
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/marketing
spring.datasource.username=marketing
spring.datasource.password=[PASS]
spring.logging.level.root=ERROR
spring.logging.level.org.hibernate=INFO
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDB103Dialect
知道出了什么问题吗?
似乎 Spring 只是没有将 Hibernate ServiceRegistry
注册为 bean。我查看了源代码,发现它的实例是在 SessionFactoryImpl
构造函数中创建的。
您可以尝试应用此 hack。
@SpringBootApplication
public class AutoWiredTest implements CommandLineRunner {
@Autowired
private EntityManagerFactory emf;
@Override
public void run(String... args)
throws Exception {
SessionFactoryImplementor sessionFactory = emf.unwrap(SessionFactoryImplementor.class);
ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry();
}
public static void main(String[] args)
throws Exception {
SpringApplication.run(AutoWiredTest.class, args);
}
}