JSF + Varios Schemas

Ola pessoal.

Estou necessitando de acordo com o usúario logado irá conectar em um schema (bd).
Ou seja, a aplicacao web terá um banco para cada cliente, como preceder?

Estou utilizando JSF 2 + Hibernate + Mysql

Alguem pode nos auxiliar??

Grato

No persistence.xml você pode ter um persistenceUnit para cada cliente.

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">

	<persistence-unit name="client1">
		
		<properties>
			
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
                         ............		
		</properties>

	</persistence-unit>

	<persistence-unit name="client2">
		
		<properties>
			
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
                         ............		
		</properties>

	</persistence-unit>

	<persistence-unit name="client3">
		
		<properties>
			
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
                         ............		
		</properties>

	</persistence-unit>

</persistence>

Ou cria um banco de dados global, com as informações dos bancos de cada cliente e cria o persistence.xml programaticamente.

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">

	<persistence-unit name="default">
		

	</persistence-unit>

</persistence>
		Map<String , Object> config = new HashMap<String, Object>();
		config.put("transaction-type", "RESOURCE_LOCAL");
		config.put("hibernate.connection.url", client.getUrl());
		config.put("hibernate.connection.driver_class", client.getDriver());
		config.put("hibernate.dialect", client.getDialect());
		config.put("hibernate.connection.username", client.getUsername());
		config.put("hibernate.connection.password", client.getPassword());

Persistence.createEntityManagerFactory("default", config);

No login você configura o banco de dados correto de cada cliente.

Cria uma classe com escopo de aplicação para fazer o cache do EntityManagerFactory.

private Map<String, EntityManagerFactory> connections = new HashMap<String, EntityManagerFactory>();
connections.put(nameBase, Persistence.createEntityManagerFactory("default", Persistence.createEntityManagerFactory("default", config));

Opa… valeu pela força, tenho certeza que esse post vai auxiliar mais pessoas que estao iniciando.

Seguinte. se optar por a configuração no xml, criando varias units… como ficaria meu “Persistence.createEntityManagerFactory” ?
Eu tenho um filtro, no qual instancia o entityManager quando aplicaçao é startada… alguma sugestao?

segue o filtro.

A ideia era ser dinâmico…

[quote]package filtros;

import java.io.IOException;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter(servletNames={“Faces Servlet”})
public class FiltroJPA implements Filter {

private EntityManagerFactory factory;

@Override
public void destroy() {
	this.factory.close();
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
	FilterChain chain) throws IOException, ServletException {
	EntityManager entityManager = this.factory.createEntityManager();
	request.setAttribute("entityManager", entityManager);
	entityManager.getTransaction().begin();
	chain.doFilter(request, response);
	try {
		entityManager.getTransaction().commit();
	} catch (Exception e) {
		entityManager.getTransaction().rollback();
	} finally {
		entityManager.close();
	}

}

@Override
public void init(FilterConfig arg0) throws ServletException {
	this.factory = Persistence.createEntityManagerFactory("base");
}

}
[/quote]

Como deixar isso dinâmico?
Obrigado

Um banco de dados pra cada cliente? como assim? se você tiver 2.000 clientes, você terá 2.000 bancos de dados? O.ô

Olá Wilson…

Então, venho desde o inicio desse tópico pesquisando e avaliando os prós e contras em relação a essa implementação.

Penso em separar as bases de dados devido alguns pontos, entre eles:

  • Desenvolvimento não se preocupa com usuários de um tenant acessando dados de outro, o servidor cuidaria disso.
  • Segurança, mas não só pela questão de um cliente acessar ou alterar os dados de outro, mas se o desenvolvedor esquecer um ?WHERE CLIENTE_ID = #? pode ser fatal.
  • Se eu tiver algum problema de atualização de versão, problema físico ou qualquer outro como banco de dados corrompido, apenas o cliente que teve o problema vai ficar parado.
  • Argumento de venda, falar ao cliente que a base dele vai ficar completamente separada da base de seu concorrente.

Porem estou vendo que essa medida complicará o deploy e manutençao de todos eles no futuro. :?

Isso é tema de discussão, aposto que muitos aqui tem opiniões diferentes, pois o tema depende te muitos fatores.

Alguém aqui utiliza essa abordagem, pode compartilhar a experiência conosco?

Não entendi muito bem, você está dizendo que em uma única aplicação, toda vez que for cadastrar um novo cliente, o sistema irá criar um novo banco de dados?
vai haver alguma diferença entre um banco e outro?

Opa, é mais ou menos por ai.

Cada usuario novo “meu” tera um banco de dados.
Digamos que um banco por empresa nova, pra melhor entender.

Sobre a aplicação, nao teras diferença de estrutura e modelagem entre eles, seria o mesmo produto.

Então… se cada “empresa” terá um banco de dados, logo cada “aplicação” trabalhará apenas com um único banco de dados… :S