001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.config.util; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; 024import ca.uhn.fhir.jpa.config.HapiFhirHibernateJpaDialect; 025import ca.uhn.fhir.jpa.config.HapiFhirLocalContainerEntityManagerFactoryBean; 026import ca.uhn.fhir.jpa.util.ISequenceValueMassager; 027import ca.uhn.fhir.util.ReflectionUtil; 028import jakarta.persistence.spi.PersistenceUnitInfo; 029import org.hibernate.boot.registry.BootstrapServiceRegistry; 030import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 031import org.hibernate.jpa.HibernatePersistenceProvider; 032import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl; 033import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; 034import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; 035import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 036import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 037 038import java.util.Map; 039 040public final class HapiEntityManagerFactoryUtil { 041 private HapiEntityManagerFactoryUtil() {} 042 043 /** 044 * This method provides a partially completed entity manager 045 * factory with HAPI FHIR customizations 046 */ 047 public static LocalContainerEntityManagerFactoryBean newEntityManagerFactory( 048 ConfigurableListableBeanFactory myConfigurableListableBeanFactory, 049 FhirContext theFhirContext, 050 JpaStorageSettings theStorageSettings) { 051 052 LocalContainerEntityManagerFactoryBean retVal = 053 new HapiFhirLocalContainerEntityManagerFactoryBean(myConfigurableListableBeanFactory); 054 055 configureEntityManagerFactory(retVal, theFhirContext, theStorageSettings); 056 return retVal; 057 } 058 059 public static void configureEntityManagerFactory( 060 LocalContainerEntityManagerFactoryBean theFactory, 061 FhirContext theFhirContext, 062 JpaStorageSettings theStorageSettings) { 063 theFactory.setJpaDialect(new HapiFhirHibernateJpaDialect(theFhirContext.getLocalizer())); 064 theFactory.setPackagesToScan("ca.uhn.fhir.jpa.model.entity", "ca.uhn.fhir.jpa.entity"); 065 theFactory.setPersistenceProvider(new MyHibernatePersistenceProvider(theStorageSettings)); 066 } 067 068 private static class MyHibernatePersistenceProvider extends HibernatePersistenceProvider { 069 070 private final JpaStorageSettings myStorageSettings; 071 072 public MyHibernatePersistenceProvider(JpaStorageSettings theStorageSettings) { 073 myStorageSettings = theStorageSettings; 074 } 075 076 /** 077 * @see MyEntityManagerFactoryBuilderImpl for an explanation of why we do this 078 */ 079 @Override 080 protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder( 081 PersistenceUnitInfo info, Map<?, ?> integration) { 082 return new MyEntityManagerFactoryBuilderImpl(info, integration); 083 } 084 085 /** 086 * This class extends the default hibernate EntityManagerFactoryBuilder in order to 087 * register a custom service (the {@link ISequenceValueMassager}, which is used in 088 * {@link ca.uhn.fhir.jpa.model.dialect.HapiSequenceStyleGenerator}. 089 * <p> 090 * In Hibernate 5 we didn't need to do this, since we could just register 091 * the service with Spring and Hibernate would ask Spring for it. This no longer 092 * seems to work in Hibernate 6, so we now have to manually register it. 093 */ 094 private class MyEntityManagerFactoryBuilderImpl extends EntityManagerFactoryBuilderImpl { 095 public MyEntityManagerFactoryBuilderImpl(PersistenceUnitInfo theInfo, Map<?, ?> theIntegration) { 096 super(new PersistenceUnitInfoDescriptor(theInfo), (Map) theIntegration); 097 } 098 099 @Override 100 protected StandardServiceRegistryBuilder getStandardServiceRegistryBuilder(BootstrapServiceRegistry bsr) { 101 StandardServiceRegistryBuilder retVal = super.getStandardServiceRegistryBuilder(bsr); 102 ISequenceValueMassager sequenceValueMassager = 103 ReflectionUtil.newInstance(myStorageSettings.getSequenceValueMassagerClass()); 104 retVal.addService(ISequenceValueMassager.class, sequenceValueMassager); 105 return retVal; 106 } 107 } 108 } 109}