init
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ConfigurableMultiTenantConnectionProvider implements MultiTenantConnectionProvider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
private transient DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public Connection getAnyConnection() throws SQLException {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseAnyConnection(Connection connection) throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String tenantIdentifier) throws SQLException {
|
||||
return changeSchema(dataSource.getConnection(), tenantIdentifier);
|
||||
}
|
||||
|
||||
public Connection changeSchema(Connection connection, String tenantIdentifier) throws SQLException {
|
||||
// connection.setSchema() 를 이용하여 schema를 설정 하려 했으나 postgresql 에서는 대문자로 넣으면 에러가
|
||||
// 발생 한다. 에러가 발생 하지 않게 하려면 applicationContext-datasource.xml 에서 스키마명을 소문자로 변경
|
||||
// 한다.
|
||||
// 일단 schema 설정을 하지 않고 사용
|
||||
String schema = DataSourceTypeManager.getDataSourceType(tenantIdentifier).getSchema();
|
||||
// connection.setSchema(schema);
|
||||
log.debug("change schema : {} connection : {}", schema, connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnwrappableAs(@SuppressWarnings("rawtypes") Class aClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> aClass) {
|
||||
throw new UnsupportedOperationException("Can't unwrap this.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import com.eactive.eai.data.jpa.BaseRepositoryImpl;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaAuditing(auditorAwareRef = "EMSAuditorAware")
|
||||
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryForEMS", transactionManagerRef = "transactionManagerForEMS", basePackages = {"com.eactive.eai", "com.eactive.apim.portal"}, repositoryBaseClass = BaseRepositoryImpl.class, includeFilters = @Filter(classes = EMSDataSource.class))
|
||||
public class EMSTenantConfiguration {
|
||||
|
||||
@Bean("entityManagerFactoryForEMS")
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactoryForEMS(
|
||||
@Qualifier(DataSourceTypeManager.MONITORING) DataSource dataSource,
|
||||
@Qualifier("hibernateProperties") Properties hibernateProperties) {
|
||||
|
||||
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
|
||||
bean.setDataSource(dataSource);
|
||||
bean.setPackagesToScan("com.eactive.eai.data", "com.eactive.eai.rms.data", "com.eactive.apim.portal");
|
||||
bean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
|
||||
bean.setJpaProperties(hibernateProperties);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean("transactionManagerForEMS")
|
||||
public TransactionManager transactionManager(@Qualifier(DataSourceTypeManager.MONITORING) DataSource dataSource,
|
||||
@Qualifier("entityManagerFactoryForEMS") EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
|
||||
jpaTransactionManager.setDataSource(dataSource);
|
||||
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
|
||||
return jpaTransactionManager;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
|
||||
import org.hibernate.annotations.Table;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class EntityTablePrinter implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
@Autowired
|
||||
public EntityTablePrinter(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (log.isDebugEnabled() && event.getApplicationContext().getParent() == null) {
|
||||
log.debug("################### TABLE INFO ###################");
|
||||
entityManagerFactory.getMetamodel().getEntities().parallelStream().forEach(this::printEntityTableInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void printEntityTableInfo(EntityType<?> entityType) {
|
||||
String entityName = entityType.getName();
|
||||
|
||||
// Hibernate Table 정보 출력
|
||||
printTableInfo(entityType, Table.class,
|
||||
table -> log.debug("Table Name : {} = {} ({})", table.appliesTo(), entityName, table.comment()));
|
||||
|
||||
// JPA Table 정보 출력
|
||||
printTableInfo(entityType, javax.persistence.Table.class,
|
||||
table -> log.debug("Table Name : {} = {}", table.name(), entityName));
|
||||
}
|
||||
|
||||
private <T extends Annotation> void printTableInfo(EntityType<?> entityType, Class<T> annotationClass,
|
||||
Consumer<T> printer) {
|
||||
T tableAnnotation = entityType.getBindableJavaType().getAnnotation(annotationClass);
|
||||
if (tableAnnotation != null) {
|
||||
printer.accept(tableAnnotation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.orm.jpa.support.SharedEntityManagerBean;
|
||||
|
||||
@Configuration
|
||||
public class JPAConfiguration {
|
||||
|
||||
@Bean("entityManager")
|
||||
public SharedEntityManagerBean entityManager(EntityManagerFactory entityManagerFactory) {
|
||||
SharedEntityManagerBean sharedEntityManagerBean = new SharedEntityManagerBean();
|
||||
sharedEntityManagerBean.setEntityManagerFactory(entityManagerFactory);
|
||||
return sharedEntityManagerBean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import com.eactive.eai.data.jpa.BaseRepositoryImpl;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
import com.eactive.kakao.rolling.TableSuffixResolver;
|
||||
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaAuditing(auditorAwareRef = "EMSAuditorAware")
|
||||
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager", basePackages = {
|
||||
"com.eactive.eai", }, repositoryBaseClass = BaseRepositoryImpl.class, excludeFilters = {
|
||||
@Filter(classes = EMSDataSource.class)
|
||||
,
|
||||
// @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { DataLoaderRepository.class })
|
||||
})
|
||||
public class MultitenantConfiguration {
|
||||
|
||||
@Bean("entityManagerFactory")
|
||||
@Primary
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
|
||||
@Qualifier("hibernateProperties") Properties hibernateProperties) {
|
||||
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
|
||||
bean.setDataSource(dataSource);
|
||||
bean.setPackagesToScan("com.eactive.eai.data", "com.eactive.eai.rms.data");
|
||||
bean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
|
||||
bean.setJpaProperties(hibernateProperties);
|
||||
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
settings.put(AvailableSettings.MULTI_TENANT, "SCHEMA");
|
||||
settings.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, configurableMultiTenantConnectionProvider());
|
||||
settings.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantIdentifierResolver());
|
||||
|
||||
bean.setJpaPropertyMap(settings);
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean("transactionManager")
|
||||
@Primary
|
||||
public TransactionManager transactionManager(DataSource dataSource, EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
|
||||
jpaTransactionManager.setDataSource(dataSource);
|
||||
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
|
||||
return jpaTransactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurableMultiTenantConnectionProvider configurableMultiTenantConnectionProvider() {
|
||||
return new ConfigurableMultiTenantConnectionProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TenantIdentifierResolver tenantIdentifierResolver() {
|
||||
return new TenantIdentifierResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TableSuffixResolver tableSuffixResolver() {
|
||||
return () -> "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.eactive.eai.rms.data.config;
|
||||
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceType;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
|
||||
|
||||
@Component
|
||||
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TenantIdentifierResolver.class);
|
||||
|
||||
@Override
|
||||
public String resolveCurrentTenantIdentifier() {
|
||||
|
||||
DataSourceType dataSourceType = DataSourceContextHolder.getDataSourceType();
|
||||
|
||||
if (dataSourceType == null) {
|
||||
dataSourceType = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.MONITORING);
|
||||
logger.debug("DataSource가 명시적으로 선택되지 않았으므로, MONITORING DataSource를 사용합니다.");
|
||||
}
|
||||
|
||||
return dataSourceType != null ? dataSourceType.getName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateExistingCurrentSessions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user