Spring Boot 2.0 builds a fat jar and the orm.xml is stored in the jar file under
/BOOT-INF/classes/META-INF/orm.xml
This leads hibernate to load the orm.xml twice. See https://github.com/spring-projects/spring-boot/issues/10363 for another case, with an easy to reproduce test.
Details: The Persistence unit is as follows
{noformat} PersistenceUnitInfo [ name: default persistence provider classname: null classloader: org.springframework.boot.loader.LaunchedURLClassLoader@1810399e excludeUnlistedClasses: true JTA datasource: null Non JTA datasource: HikariDataSource (HikariPool-1) Transaction type: RESOURCE_LOCAL PU root URL: file:path to jar.jar Shared Cache Mode: UNSPECIFIED Validation Mode: AUTO Jar files URLs [] Managed classes names [ ... snip ... ] Mapping files names [ META-INF/orm.xml] Properties [] {noformat}
The scanner finds the orm in the jar file, but the logic inside `org.hibernate.boot.model.process.internal.ScanningCoordinator#applyScanResultsToManagedResources` leads to the file being loaded a second time, causing this exception.
{noformat} Caused by: java.lang.IllegalStateException: Duplicate XML entry for foo.Bar at org.hibernate.cfg.annotations.reflection.XMLContext.addClass(XMLContext.java:150) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.cfg.annotations.reflection.XMLContext.addDocument(XMLContext.java:115) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.<init>(AnnotationMetadataSourceProcessorImpl.java:95) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.<init>(MetadataBuildingProcess.java:156) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:150) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935) ~[hibernate-core-5.3.3.Final.jar!/:5.3.3.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] ... 169 common frames omitted
{noformat}
This can be fixed with a custom scanner:
{code: kotlin java } // kotlin code class StandardScannerFixed(descriptor: ArchiveDescriptorFactory) : StandardScanner(descriptor) { constructor() : this(StandardArchiveDescriptorFactory.INSTANCE)
override fun scan(environment: ScanEnvironment?, options: ScanOptions?, parameters: ScanParameters?): ScanResult { val scan = super.scan(environment, options, parameters) return ScanResultImpl( scan.locatedPackages, scan.locatedClasses, scan.locatedMappingFiles.map { MappingFileDescriptorImpl(it.name.removePrefix("BOOT-INF/classes/"), it.streamAccess) }.toSet() ) } } {code}
|
|