У Grails есть плагин с несколькими арендаторами для единой базы данных и многопользовательский плагин для нескольких баз данных, но один для нескольких баз данных больше не поддерживается/поддерживается , Есть ли способ, которым я могу вместо этого использовать Spring или Hibernate для многозадачного многозадачного приложения Grails?Многопользовательская аренда Spring или Hibernate для приложений с множеством баз данных Grails
ответ
Вы можете использовать Hibernate Multitenancy описано здесь http://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch16.html
ИЛИ
Вы можете также рассмотреть вопрос о Спринга AbstractRoutingDataSource
Основная идея заключается в том, что DataSource маршрутизации выступает в качестве посредника - время «реальный» DataSource может быть определен динамически во время выполнения на основе ключа поиска.
https://spring.io/blog/2007/01/23/dynamic-datasource-routing/
Вы можете найти новые post, что дает примерное использование в спящий режим, суть решения, которое вы можете найти в следующих двух фрагментах
public class MyRoutingDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
String language = LocaleContextHolder.getLocale().getLanguage();
System.out.println("Language obtained: "+ language);
return language;
}
}
возвращаемое значение будет используемый в качестве дискриминатора для источника данных, следующая конфигурация устанавливает отображение
<bean id="dataSource" class="com.howtodoinjava.controller.MyRoutingDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="en" value-ref="concreteDataSourceOne"/>
<entry key="es" value-ref="concreteDataSourceTwo"/>
</map>
</property>
</bean>
Интересно. Я не знал о Spring DataSource Routing. Я собираюсь это прочитать. сделайте пример.Если бы также был способ добавить/удалить dataSources во время работы приложения, то это потрясающе (по крайней мере, для чего мне нужно). Спасибо. В любом случае, я не думаю, что есть способ сделать это и все преимущества GORM. – ionutab
Вот как я использую hibernate multitenancy с SCHEMA. Может быть, это будет полезно для вас.
applicationContext.xml
...
<bean id="multiTenantConnectionProvider" class="org.myapp.MyAppMultiTenantConnectionProvider"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="org.myapp.entities"/>
<property name="multiTenantConnectionProvider" ref="multiTenantConnectionProvider"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">org.myapp.MyAppTenantIdentifierResolver</prop>
...
</props>
</property>
</bean>
...
MyAppMultiTenantConnectionProvider.java
public class MyAppMultiTenantConnectionProvider implements MultiTenantConnectionProvider {
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
//This is where your tenant resolving logic will be implemented
return MyMultitenantConnectionPool.getConnection(tenantIdentifier);
}
}
MyAppTenantIdentifierResolver.java
public class MyAppTenantIdentifierResolver implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
/*
This is where you determine which tenant to use.
In this app SpringSecurity used for this purpose.
TenantUser class extends org.springframework.security.core.userdetails.User with tenant information.
*/
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) return "";
if (authentication.getPrincipal() instanceof TenantUser) {
TenantUser user = (TenantUser) authentication.getPrincipal();
return user.getTenant();
} else return "";
}
@Override
public boolean validateExistingCurrentSessions() {
return false;
}
}
Прежде всего, я хочу поблагодарить вас. Во-вторых, я должен сказать, что я не очень хорошо разбираюсь в концепциях, которые вы здесь изложили, и что я немного смущен. Как класс «MyMultite» nantConnectionPool ". Есть ли какой-либо особый тип логики внутри него или он просто создает соединение в зависимости от арендатора? 2. Вызывается ли «getConnection» для создания экземпляра сеанса или для запроса? 3. Есть ли для этого общественная рабочая демонстрация? – ionutab
1 & 2) Похоже, что getConnection() вызывается для каждого запроса, поэтому «MyMultiTenantConnectionPool» должен реализовывать создание соединения и адекватную стратегию объединения. В нашем приложении используется отдельный db для хранения информации о арендаторах, статусе арендатора, соответствующих базах данных и т. Д. На данный момент у меня есть MyTenantManager для поддержки этой «мета» базы данных. Таким образом, MyMultitenantConnectionPool извлекает db-url из MyTenantManager и создает экземпляры соединений, используя метод starting. 3) Извините, но это коммерческий проект, и я не имею права публиковать источник. – Lea32
Спасибо. Не уверен, что вы подразумеваете под «схемотехническим подходом» ...? Я думаю, что вы имели в виду общую базу данных для арендаторов с отдельной схемой для каждого арендатора, но ваш комментарий, похоже, указывает на другое. – Daniel
В нашем случае мы используем LocalContainerEntityManagerFactoryBean, где мы создаем multiTenantMySQLProvider.
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="domain"/>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<entry key="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.multiTenancy" value="SCHEMA" />
<entry key="hibernate.multi_tenant_connection_provider" value-ref="mySQLMultiTenantConnectionProvider" />
<entry key="hibernate.tenant_identifier_resolver" value-ref="tenantIdentifierResolver" />
</map>
</property>
</bean>
<bean id="tenantService"
class="multitenancy.service.impl.TenantServiceImpl">
<property name="defaultTenantId" value="${multitenancy.defaultTenantId}" />
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
<bean id="connectionProvider"
class="multitenancy.hibernate.ConnectionProviderImpl" lazy-init="false">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="mySQLMultiTenantConnectionProvider"
class="multitenancy.hibernate.MySQLMultiTenantConnectionProviderImpl" lazy-init="false">
<property name="connectionProvider" ref="connectionProvider" />
<property name="tenantIdentifierForAny" value="${multitenancy.tenantIdentifierForAny}" />
<property name="schemaPrefix" value="${multitenancy.schemaPrefix}" />
</bean>
<bean id="tenantIdentifierResolver"
class="multitenancy.hibernate.TenantIdentifierResolverImpl" lazy-init="false">
<property name="tenantService" ref="tenantService" />
</bean>
<bean id="tenantIdentifierSchedulerResolver"
class="security.impl.TenantIdentifierSchedulerResolverImpl" lazy-init="false">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
А вот реализация MySQLMultiTenantConnectionProviderImpl
public class MySQLMultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider, ServiceRegistryAwareService, Stoppable {
private static final Logger LOGGER = LoggerFactory.getLogger(MySQLMultiTenantConnectionProviderImpl.class);
@Setter
private ConnectionProvider connectionProvider;
@Setter
private String tenantIdentifierForAny;
@Setter
private String schemaPrefix;
@Override
public Connection getAnyConnection() throws SQLException {
return connectionProvider.getConnection();
}
@Override
public void releaseAnyConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection(connection);
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
String schema = schemaPrefix + tenantIdentifier;
try {
LOGGER.debug("setting schema in DB Connection : {}" , schema);
connection.createStatement().execute("USE " + schema);
}
catch (SQLException e) {
throw new HibernateException(
"Could not alter JDBC connection to specified schema [" + schema + "]", e
);
}
return connection;
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
try {
connection.createStatement().execute("USE " + tenantIdentifierForAny);
}
catch (SQLException e) {
LOGGER.error(" error on releaseConnection. The connection will be not closed. SQLException : {}" , e);
// on error, throw an exception to make sure the connection is not returned to the pool.
throw new HibernateException(
"Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e
);
}
// I follow the hibernate recommendation and we don't return the connetion to the pool.
connectionProvider.closeConnection(connection);
}
@Override
public boolean supportsAggressiveRelease() {
return true;
}
@Override
public void stop() {
}
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals(unwrapType) ||
MultiTenantConnectionProvider.class.equals(unwrapType) ||
AbstractMultiTenantConnectionProvider.class.isAssignableFrom(unwrapType);
}
@Override
public <T> T unwrap(Class<T> unwrapType) {
if (isUnwrappableAs(unwrapType)) {
return (T) this;
}
throw new UnknownUnwrapTypeException(unwrapType);
}
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
}
}
- 1. Многопользовательская аренда с несколькими завихрениями
- 2. Многопользовательская аренда Google Analytics
- 3. Многопользовательская связь: Spring Vs Hibernate
- 4. Spring + Hibernate - несколько баз данных
- 5. Проблема с множеством баз данных?
- 6. Использование Hibernate + Spring 3 транзакционных баз данных
- 7. Spring + Hibernate + JPA + несколько баз данных
- 8. Многопользовательская база данных для настольных приложений
- 9. многопользовательская конфигурация с множеством внешних источников
- 10. Управление транзакциями для нескольких баз данных Использование Spring & Hibernate
- 11. Проблемы миграции баз данных Grails с помощью пароля безопасности Spring
- 12. Spring + Hibernate баз данных инициализируется с данными выборки
- 13. Несколько баз данных Grails
- 14. Mutli аренда приложений в laravel 5?
- 15. Как использовать несколько баз данных с Spring MVC и Hibernate?
- 16. Создание нескольких баз данных или схем с помощью Spring JDBC
- 17. Является Spring + Hibernate лучшим для веб-приложений?
- 18. Многопользовательская аренда: какое преимущество предоставляет один-дБ на одного арендатора?
- 19. Разработка баз данных для агрономических приложений баз данных
- 20. Подсчет приложений баз данных
- 21. Заполнение dropdownlists для приложений с множеством арендаторов
- 22. Несколько баз данных + JNDI с данными Spring JPA для инициализации
- 23. Хостинг баз данных для настольных приложений
- 24. Поддержка нескольких баз данных с использованием hibernate
- 25. Невозможно подключить несколько баз данных PostgreSQL, используя SPRING + HIbernate
- 26. лучшие практики для приложений баз данных
- 27. Могу ли я использовать один пул данных для нескольких баз данных с Spring/Hibernate/c3p0?
- 28. хостинг баз данных для настольных приложений
- 29. Hibernate с использованием нескольких баз данных
- 30. Модели приложений Django для разных баз данных
Ответ является наиболее вероятным. И это зависит от ваших требований. Многопользовательская аренда - это не то же самое определение для всех. Чем больше информации о ваших требованиях вы можете предоставить лучший ответ, который вы можете получить. Возьмем, например, как вам нужно идентифицировать своего арендатора по запросу? Это в URL-адресе, основанном на хосте? Домен? Источник IP? Выбрано пользователем при входе в систему? Связано с логином? Центральная база данных для обеспечения безопасности и индивидуальная для каждого арендатора? И т. Д. –
«Центральная база данных для обеспечения безопасности и индивидуальная для каждого арендатора?»: Да, Stormpath DB для обеспечения безопасности и наш собственный - возможно, индивидуальный - DB (ы) для информации арендатора. «Как вам нужно идентифицировать своего арендатора по запросу?«: Я надеялся сделать это на основе имени пользователя (т. Е.« Связанный с логином »). Организация/аренда будет выбрана при регистрации. Если это невозможно, пользователи могут войти в субдомен, специфичный для их аренды. – Daniel
Другой вопрос: насколько сложно это сделать? Вам нужно быстро развернуть это, поэтому я рассматриваю возможность использования Django. – Daniel