以下是一个使用本地SQL和Hibernate多租户的示例:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactory",
basePackages = { "com.example.repository" }
)
public class HibernateConfig {
@Autowired
private DataSource dataSource;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.model");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.multiTenancy", "SCHEMA");
properties.setProperty("hibernate.multi_tenant_connection_provider", "com.example.MultiTenantConnectionProviderImpl");
properties.setProperty("hibernate.tenant_identifier_resolver", "com.example.CurrentTenantIdentifierResolverImpl");
em.setJpaProperties(properties);
return em;
}
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
MultiTenantConnectionProvider
接口的类,用于提供多租户的数据库连接:public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {
@Autowired
private 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 {
Connection connection = getAnyConnection();
Statement statement = connection.createStatement();
statement.execute("USE " + tenantIdentifier); // 切换到指定的租户数据库
return connection;
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
Statement statement = connection.createStatement();
statement.execute("USE default_database"); // 切换回默认数据库
connection.close();
}
@Override
public boolean supportsAggressiveRelease() {
return false;
}
@Override
public boolean isUnwrappableAs(Class aClass) {
return false;
}
@Override
public T unwrap(Class aClass) {
return null;
}
}
CurrentTenantIdentifierResolver
接口的类,用于解析当前租户的标识符:public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
// 从上下文中获取当前租户的标识符
String tenantIdentifier = TenantContext.getCurrentTenant();
if (tenantIdentifier != null) {
return tenantIdentifier;
}
return "default_database"; // 默认数据库
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
public class TenantContext {
private static final ThreadLocal currentTenant = new ThreadLocal<>();
public static void setCurrentTenant(String tenantIdentifier) {
currentTenant.set(tenantIdentifier);
}
public static String getCurrentTenant() {
return currentTenant.get();
}
public static void clear() {
currentTenant.remove();
}
}
@Service
public class MyService {
@Autowired
private MyEntityRepository myEntityRepository;
public void doSomething(String tenantIdentifier) {
try {
TenantContext.setCurrentTenant(tenantIdentifier); // 设置当前租户标识符
// 执行数据库操作
List entities = myEntityRepository.findAll();
// ...
} finally {
TenantContext.clear(); // 清除当前租户标识符
}
}
}
这是一个基本的示例,你可以根据自己的需求进行扩展和修改。