• Nenhum resultado encontrado

Introdução a Multi-Tenancy Com Hibernate 4

N/A
N/A
Protected

Academic year: 2021

Share "Introdução a Multi-Tenancy Com Hibernate 4"

Copied!
23
0
0

Texto

(1)

www.devmedia.com.br

www.devmedia.com.br

[ve

[versão rsão para ipara impressãompressão]]

Link original: http://www.devmedia.com.br/articles/viewcomp.asp?comp=29114 Link original: http://www.devmedia.com.br/articles/viewcomp.asp?comp=29114

Introdução

Introdução a Multi-

a Multi-Tenancy

Tenancy

com Hibernate 4

com Hibernate 4

Este artigo apresenta a funcionalidade, do Hibernate, que

Este artigo apresenta a funcionalidade, do Hibernate, que

provê mecanismos de suporte à arquitetura Multi-Tenant.

provê mecanismos de suporte à arquitetura Multi-Tenant.

Artigo do tipo

Artigo do tipo TutorialTutorial

Recursos especiais neste artigo:

Recursos especiais neste artigo:

Conteúdo

Conteúdo sosobre Novibre Novidadedadess

 Aut

 Autores: Marcos de Melo ores: Marcos de Melo Siega eSiega e Everton Coimbra de AraújoEverton Coimbra de Araújo

Suporte a Multi-Tenancy com Hibernate 4

Suporte a Multi-Tenancy com Hibernate 4

Est

Este artigo apresente artigo apresenta a funcia a funcionalionalidade, agregada à vedade, agregada à versão rsão 4 do 4 do frameframework Hiwork Hibernate, quebernate, que

pro

provê mevê mecanicanismos smos de sde supouporte à arquitetura rte à arquitetura MulMulti-Tenant ti-Tenant (vá(vários rios clclieientesntes, logica, logicamementente

i

isosolaladosdos, util, utilizaizando ndo os os memesmos smos recrecursos ursos fífísicos). Alésicos). Além de demm de demonstonstrar os rar os aspecaspectos tos destedeste

novo recurso, expõe-se uma contextualização sobre Hibernate e Multi-Tenancy, e então,

novo recurso, expõe-se uma contextualização sobre Hibernate e Multi-Tenancy, e então,

ao final, implementa-se um exemplo prático utilizando esta nova funcionalidade.

ao final, implementa-se um exemplo prático utilizando esta nova funcionalidade.

Em

Em que situação o tema que situação o tema é útil é útil

Arquitetos de software encontram grandes desafios ao construir modelos arquiteturais

Arquitetos de software encontram grandes desafios ao construir modelos arquiteturais

SaaS (So

SaaS (Software como sftware como servierviço, do ço, do inglinglês Sês Softoftware aware as s a Servia Service) que ace) que apresentem umapresentem uma

infraestrutura de dados diferenciada, podendo não contar com servidores locais e

infraestrutura de dados diferenciada, podendo não contar com servidores locais e

infraestrutura própria, tendo que dispor todos os dados em um espaço compartilhado.

infraestrutura própria, tendo que dispor todos os dados em um espaço compartilhado.

Fatores como estes influenciam diretamente na capacidade de gerência, monitoramento e

Fatores como estes influenciam diretamente na capacidade de gerência, monitoramento e

até mesmo na segurança dos dados.

(2)

Na medida em que a linguagem Java começou a ganhar destaque em ambientes

Na medida em que a linguagem Java começou a ganhar destaque em ambientes

corporativos, notou-se rapidamente que um tempo excessivo era gasto com a

corporativos, notou-se rapidamente que um tempo excessivo era gasto com a

codificação de instruções SQL e com código JDBC capaz de interpretá-las.

codificação de instruções SQL e com código JDBC capaz de interpretá-las.

O processo de desenvolvimento sofre influência direta deste aspecto negativo, pois há

O processo de desenvolvimento sofre influência direta deste aspecto negativo, pois há

uma imensa queda de produtividade quando o desenvolvedor torna-se responsável por

uma imensa queda de produtividade quando o desenvolvedor torna-se responsável por

criar tais instruções manualmente, cabendo a ele tratar da mudança do paradigma

criar tais instruções manualmente, cabendo a ele tratar da mudança do paradigma

orientado a objetos para o mapeamento objeto relacional e vice-versa. Este

orientado a objetos para o mapeamento objeto relacional e vice-versa. Este

procedimento implica na necessidade de escrita de muitas linhas de código, criando um

procedimento implica na necessidade de escrita de muitas linhas de código, criando um

enorme obs

enorme obstáculo para o destáculo para o desenvolvenvolvedor, quedor, que fie ficará ecará encarrencarregado gado de tratar da pde tratar da persistênciaersistência

e recuperação de seus objetos utilizando uma linguagem de consulta estruturada.

e recuperação de seus objetos utilizando uma linguagem de consulta estruturada.

A ex

A existência istência destdesta diva divergênciergência entre o moda entre o modelelo oo orierientado ntado a obja objetos etos e o modelo relae o modelo relacicionalonal

estimul

estimulou ou o do desenvolviesenvolvimemento nto de mede mecanicanismos smos que contque contornasornassem este psem este problemroblema. Uma. Uma dasa das

princi

principais ferramepais ferramentas ntas que sque surgiramurgiram, b, buscando uscando resoresolvlver ester esta incompatia incompatibilbilidaidade, fode, foi oi o

Hi

Hibernate. Esbernate. Este te frameframeworkwork aplica técnicas de mapeamento objeto relacional para resolveraplica técnicas de mapeamento objeto relacional para resolver

a dissonância entre os modelos.

a dissonância entre os modelos.

Os

Os frameworksframeworks de mapeamento objeto relacional, como o Hibernate, permitem mapear a de mapeamento objeto relacional, como o Hibernate, permitem mapear a

representação dos dados de um modelo de objeto para um modelo de dados relacional e

representação dos dados de um modelo de objeto para um modelo de dados relacional e

seu respectivo esquema de banco de dados, utilizando arquivos de configuração no

seu respectivo esquema de banco de dados, utilizando arquivos de configuração no

formato XML e anotações Java.

formato XML e anotações Java.

Tais ferrame

Tais ferramentas ntas de ORM, alde ORM, além de tratar da pém de tratar da persistência e reersistência e recuperaçcuperação doão dos s dadosdados,,

devem

devem garantir que as informações pgarantir que as informações permaermaneçaneçam ím íntegras ntegras e segurase seguras, s, seja qual for aeja qual for a

arquitetura de software adotada para a solução. Diante da constante necessidade de

arquitetura de software adotada para a solução. Diante da constante necessidade de

garantia destes fatores nos mais variados contextos, a versão 4 do Hibernate oferece

garantia destes fatores nos mais variados contextos, a versão 4 do Hibernate oferece

suporte para uma das arquiteturas que tem ganhado bastante destaque, denominada

suporte para uma das arquiteturas que tem ganhado bastante destaque, denominada

Mul

Multi-Tenancy. Estti-Tenancy. Este novo e novo recurso recurso vai vai de encontro de encontro ao aumeao aumento nto do do número de aplinúmero de aplicaçcaçõesões

que estão sendo desenvolvidas voltadas para a nuvem, ou ambientes onde os recursos

que estão sendo desenvolvidas voltadas para a nuvem, ou ambientes onde os recursos

disponíveis são compartilhados.

disponíveis são compartilhados.

Com base nisso, este artigo aborda as principais características deste recurso adicionado

Com base nisso, este artigo aborda as principais características deste recurso adicionado

ao Hibe

ao Hibernate, srnate, suas puas posossíveisíveis s aplaplicicações e um exações e um exememplo splo simimpleples s de como de como emempregá-lo.pregá-lo.

Hibernate

Hibernate

O Hibernate é um framework para mapeamento objeto relacional e consulta a bases de

O Hibernate é um framework para mapeamento objeto relacional e consulta a bases de

dados de código aberto e que é distribuído sob a licença LGPL. Ele

(3)

transparência no processo de armazenamento de objetos em bancos de dados relacionais para o desenvolvedor, tirando dele a necess idade de se preocupar com a forma com que estes objetos serão persistidos ou recuperados. Es ta transparência permite que o desenvolvedor concentre-se somente nas características e nos problemas a serem resolvidos pela aplicação.

O Hibernate poss ibilita que os desenvolvedores ut ilizem a convenção POJO (Objetos Simples em Java, do inglês Plain Old Java Objects) para construir a camada de modelo das aplicações. No entanto, ele não é apenas uma solução ORM, mas sim uma coleção de projetos que fornecem funcionalidades que vão além do mapeamento objeto relacional. Uma dessas funcionalidades é o suporte ao isolamento de dados para os vários clientes de uma aplicação, também conhecido como Multi-Tenancy, sobre o qual abordaremos a partir de agora.

O que é Multi-Tenancy?

Em uma aplicação que atende diversos clientes simultaneamente, é fundamental que uma possível falha na operação de um cliente não afete os demais. Desta maneira, em

modelos onde os recursos computacionais são amplamente compartilhados, este cenário requer uma atenção especial.

Para as organizações, mecanismos que garantam a integridade dos dados , seu mais importante acervo, são extremamente importantes. Por est e motivo, elas preferem manter seus softwares e bancos de dados instalados em hardwares pertencentes à própria organização, a ter que confiá-los a estruturas inadequadas de fornecedores de hospedagem.

Com o advento da computação em nuvem, e a tendência de novas aplicações operarem e serem disponibilizadas, cada vez mais, por esta tecnologia, modelos arquiteturais

adequados que forneçam apoio à integridade dos dados se tornam imprescindíveis. Diante deste cenário, o nde a utilização dos recursos físicos é feita de maneira

compartilhada e a garantia de integridade e segurança dos dados é vital, uma so lução tem ganhado destaque por permitir o isolamento lógico dos recursos. Esta solução é o modelo chamado de Multi-Tenancy.

O termo Multi-Tenancy é aplicado ao desenvolvimento de software para indicar uma

arquitetura na qual uma única instância de determinada aplicação serve simultaneamente a vários clientes (tenants). Cada um dos clientes pode receber a habilidade de customizar

(4)

partes da aplicação, tais como a cor da interface com o usuário ou as regras de negócio (por meio de configurações), porém, não são capazes de modificar o código do aplicativo. Est e modelo arquitetural é comumente utilizado em soluções SaaS para isolar as

informações (dados, armazenados em um banco de dados, e customizações, por

exemplo) dos diferentes clientes. O uso desse modelo para tal propósito é comumente chamado de “Multi-Tenant de dados”.

Multi-Tenancy no Hibernate

Como de costume, o Hibernate se esfo rça para manter a API simples e isolada de qualquer detalhe da complexidade de sua implementação. Neste sentido, o uso deste novo recurso resume-se basicamente a especificar o identificador do cliente no processo de abertura de uma nova sessão (session) e indicar, no processo de configuração do framework , a estratégia que será adotada para isolar os dados.

Entre as diferentes estratégias de implementação do Multi-Tenancy, estão as seguintes: 1. Criar um banco de dados ou esquema de dados exclusivo para cada cliente;

2. Usar o mesmo banco de dados ou esquema para todos os clientes, mas com uma coluna adicional em todas as tabelas (um id_tenant, por exemplo) para filtrar os dados. O Hibernate, em sua versão 4, suporta apenas o primeiro item. O suporte para o

segundo está planejado para acompanhar a versão 5.0 do framework.

Banco de dados exclusivo por cliente

Nesta abordagem, os dados de cada cliente são mantidos em uma instância de banco de dados separada fisicamente, como demonstra a Figura 1.

(5)

Figura 1. Base de dados exclusiva por cliente.

Neste modelo, conexõ es JDBC apontam especificamente para cada banco de dados. Deste modo, cada cliente utilizará apenas a conexão que lhe pertence, e as modificações feitas por cada um dos inquilinos não afetará os dados e configurações dos demais.

(6)

Adota-se este modelo através da definição de um pool  de conexões JDBC por cliente, de modo que a seleção do poo l  a ser utilizado ocorre com base em um identificador

associado ao usuário logado.

Esquema exclusivo por cliente

Nesta abordagem, os dados de cada cliente são mantidos em diferentes esquemas de uma inst ância compartilhada de banco de dados , conforme ilustra a Figura 2.

Figura 2. Base de dados compartilhada por vários clientes com separação por esquemas.

(7)

Ao empregar este modelo, teremos duas maneiras distintas para definir as conexões JDBC:

1. As conexões podem apont ar especificamente para cada esquema, de maneira análoga ao modelo de banco de dados exclusivo por cliente. Contudo, este método s ó pode ser adotado se o driver  de conexão com a base de dados suportar a nomeação do esquema padrão por meio de sua URL, ou se o mecanismo de pooling suportar a nomeação de um esquema para utilizar suas conexões. Ao empregar este método, haverá um poo l de

conexões JDBC distinto po r cliente, onde o pool a ser utilizado é selecionado com base no identificador associado ao cliente logado;

2. As conexões poderiam apontar para a própria base de dados (utilizando algum

esquema padrão), e a mudança de esquema ocorreria através do uso do comando SQL SET SCHEMA (ou similar) pela aplicação. Ao utilizar esta técnica, apenas um pool de conexões JDBC é delegado para atender a todos os clientes, e antes de ocorrer o

consumo da conexão, haveria a alteração para o esquema nomeado com o identificador associado ao cliente logado na aplicação.

Implementação do modelo Multi-Tenancy com

Hibernate

A fim de ilustrar o suporte ao modelo Multi-Tenancy, propõe-s e a criação de uma aplicação de exemplo, onde a abordagem adotada será a de esquema exclusivo por cliente. A solução proposta terá como finalidade realizar a persistência de dados de acordo com tal separação e apresentar os resultados obtidos. Antes de começar a

desenvolver esta solução, no entanto, faz-se necessário obter todos os arquivos citados a seguir.

Para contar com o Hibernate é preciso baixar os arquivos do framework e colocá-los no classpath da aplicação. Tais arquivos podem ser obtidos no site oficial da ferramenta (ver seção Links). Lá se encontram também instruções sobre como utilizá-la adequadamente. No exemplo trabalhado, optou-se pelo uso do MySQL, mas nada impede que o

desenvolvedor utilize outro SGBD. A adoção do MySQL cria a necessidade de obter e adicionar o arquivo JAR correspondente ao seu driver no diretório lib, além de incluí-lo no classpath, do mesmo modo como foram adicionados os arquivos do Hibernate.

Assim, com o ambiente de desenvolvimento instalado e corretamente configurado, pode ser dado início ao processo de implementação da aplicação exemplo.

(8)

Criação dos esquemas e tabelas

Antes de começar a implementação do projeto, utiliza-se a ferramenta MySQL Command Line Client para criar dois esquemas na instância do MySQL. Cada um dos esquemas definidos pertencerá exclusivamente ao cliente cujo nome lhe identifica. A Listagem 1 demonstra os comandos utilizados para este processo.

Listagem 1. Inst ruções utilizadas para a criação dos esquemas.

mysql> CREATE SCHEMA cliente1; mysql> CREATE SCHEMA cliente2;

Após a definição dos esquemas, vamos criar uma tabela em cada um deles. Para o exemplo, nomearemos estas tabelas como Pessoa, e ambas terão a mesma estrutura. A Listagem 2 apresenta as instruções utilizadas na criação das tabelas. Cada uma

pos sui, basicamente, dois atributos, um identificador e um nome. Decidiu-se por replicar a estrutura nos dois esquemas apenas para facilitar a apresentação do exemplo.

Listagem 2. Inst ruções utilizadas na criação das tabelas.

mysql> CREATE TABLE ‘cliente1’.’pessoa’ ( ‘id’ INT NOT NULL, ‘nome’ VARCHAR(45 NULL, PRIMARY KEY(‘id’));

mysql> CREATE TABLE ‘cliente2’.’pessoa’ ( ‘id’ INT NOT NULL, ‘nome’ VARCHAR(45 NULL, PRIMARY KEY(‘id’));

Com a base de dados configurada e seus esquemas definidos, pode-se iniciar o desenvolvimento da aplicação que utilizará a funcionalidade de Multi-Tenancy.

Criação do projeto

Para começar, é preciso criar um novo projeto do tipo Java Project  no Eclipse e definir algumas características da aplicação. Ass im, deve-se nomear o projeto, definir sua

localização, o ambiente de execução e optar por um layout para separar adequadamente os arquivos de extensão .class e .java, como demonstrado na Figura 3.

(9)

Figura 3. Janela do wizard para criação de um novo projeto.

Para finalizar este processo, especifique as bibliotecas que serão adicionadas ao classpath, a fim de atender os requisitos de dependência da nova aplicação, como realizado na Figura 4. Caso as bibliotecas não estejam disponíveis para seleção, o desenvolvedor po de facilmente configurá-las utilizando a opção User Libraries.

(10)

Figura 4. Janela do wizard para definição das configurações de construção do projeto. Além de adicionar as bibliotecas no classpath, também é importante colocar tais arquivos (JARs do Hibernate e do MySQL) na pasta lib do projeto. Caso a IDE não crie tal pasta automaticamente, o desenvolvedor deve criá-la manualmente.

O processo de adição de tais arquivos pode ser realizado por meio da técnica de Drag-and-Drop (Arrastar e Soltar). O resultado de tal procedimento é apresentado na Figura 5.

(11)

Figura 5. Resultado da adição dos arquivos de dependência no projeto.

Neste momento, após ter criado o projeto, faz- se necessário definir uma faceta para ele. Facetas permitem que projetos Java EE obtenham, através de configuração, suporte para várias outras tecnologias. O uso deste recurso deve-se pelo emprego da IDE Eclipse, sendo que outros ambientes de desenvolvimento não agregam tal conceito. A este exemplo fo i adicionada a faceta JPA, como expos to na Figura 6.

(12)

Figura 6. Janela do wizard de configuração das propriedades do projeto.

A s eleção desta faceta obriga o desenvolvedor a realizar algumas configurações básicas, tais como, indicar a biblioteca que contém os arquivos de implementação do JPA e ajustar a conexão com a base de dados utilizada. Um link (Further configuration required...)

emitido pela própria IDE e que estará disponível, em destaque, na parte inferior da janela do Wizard  de ajustes das propriedades do projeto, dá acesso às propriedades da

conexão, que deve ser configurada. O resultado dessa etapa pode ser observado na Listagem 3.

Listagem 3. Arquivo persistence.xml gerado automaticamente após o processo de configuração da faceta JPA.

<?xml version="1.0" encoding="UTF-8"?>

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

(13)

  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="MultiTenancyApp">

  </persistence-unit> </persistence>

Como resultado do processo de configuração o arquivo persistence.xml  é gerado, e deve ser modificado de acordo com as propriedades do banco de dados e seguindo o padrão definido pelo provedor de persistência. A Listagem 4 apresenta o resultado de tal

procedimento.

Listagem 4. Configuração do arquivo persistence.xml .

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0"   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"> <persistence-unit name="MultiTenancyApp"   transaction-type="RESOURCE_LOCAL">   <provider>   org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/cliente1" />

<property name="hibernate.connection.username" value="user" /> <property name="hibernate.connection.password" value="password" /> <property name="hibernate.multiTenancy" value="SCHEMA" />

  </properties>

  </persistence-unit>   </persistence>

Implementação da aplicação exemplo

Tendo criado o projeto e realizadas as devidas configurações, dá-se início ao

desenvolvimento da classe que demonstrará o uso do suporte ao modelo Multi-Tenant, e das demais classes necessárias para compor a solução.

(14)

Para começar, uma nova classe Java, denominada Pessoa, deve ser criada. Esta classe terá a finalidade de representar a tabela presente em ambos os esquemas do banco de dados. Feito isto, faz-se necessário implementá-la, definindo seus atributos, métodos  “acessores” e mapeando-a com anotações, conforme realizado na Listagem 5. E válido

lembrar também de mapeá-la no arquivo persistence.xml , para que a unidade de persistência consiga gerenciá-la.

Listagem 5. Implementação da classe Pessoa.

package br.edu.utfpr.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id;

//Mapeamento da classe com sua representação na base de dados @Entity(name = "Pessoa")

public class Pessoa implements Serializable {

private static final long serialVersionUID = 1L; //Definição de atributo identificador

  @Id

private Long id; private String nome;

// Métodos get/set omitidos }

Após realizar a implementação da classe Pessoa, é preciso criar um arquivo XML de configurações para o Hibernate. Este arquivo é similar ao persitence.xml  quanto a finalidade, variando apenas na sintaxe e possuindo alguns recursos extras de configuração específicos do Hibernate. O arquivo dever ser criado na pasta src e

nomeado como hibernate.cfg.xml . O corpo deste arquivo pode ser visto na Listagem 6. Listagem 6. Arquivo de configurações do Hibernate – hibernate.cfg.xml.

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">   <hibernate-configuration>   <session-factory> <property name="hibernate.ejb.naming_strategy">   org.hibernate.cfg.ImprovedNamingStrategy"</property> <property name="hibernate.connection.driver_class">

(15)

  com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">   jdbc:mysql://localhost:3306/cliente1</property> <property name="hibernate.connection.username">   user</property> <property name="hibernate.connection.password">   Password</property> <property name="hibernate.hbm2ddl.auto">   create-drop</property> <property name="hibernate.show_sql">   true</property> <property name="hibernate.format_sql">   true</property> <property name="hibernate.dialect">   org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.multiTenancy">   schema</property> <property name="hibernate.multi_tenant_connection_provider">   br.edu.utfpr.application.MultiTenantConnectionProviderImpl</property> <mapping class="br.edu.utfpr.modelo.Pessoa" />   </session-factory>   </hibernate-configuration>

Neste arquivo existem duas propriedades que são extremamente importantes, pois são elas que determinam o modelo de abordagem Multi-Tenancy que será utilizada pela

aplicação. A primeira é a hibernate.multiTenancy, que é responsável por definir que o modelo que será utilizado será baseado em um esquema exclusivo por cliente, e a outra propriedade é a hibernate.multi_tenant_connection_provider, que define qual será a classe responsável por obter as conexões de acordo com o identificador do cliente. As demais propriedades devem ser configuradas de acordo com a base de dados utilizada, com as classes de modelo que estarão passiveis de persistência, e outras preferências do desenvolvedor.

Tendo configurado o arquivo XML com as propriedades do Hibernate, realiza-se então a criação das demais classes que compõem o projeto. Estas classes são responsáveis por utilizar efetivamente o recurso de Multi-Tenancy baseado no esquema exclusivo por cliente.

A Listagem 7 apresenta a classe ConnectionProviderBuilder com alguns comentários sobre algumas das suas características. Ela disponibiliza dois métodos que, em conjunto, são responsáveis por fornecer conexões configuradas para o SGBD escolhido. O método

(16)

getConnectionProviderProperties(), por exemplo, s e encarregará de construir e devolver um arquivo de propriedades com todos os parâmetros necessários para estabelecer tais conexões, enquanto o método buildConnectionProvider() utilizará este recurso para criar uma inst ância da class e

DriverManagerConnectionProviderImpl, que tem como papel fornecer conexões valendo-se dos recursos da classe DriverManager.

Listagem 7. Classe construtora de provedores de conexões – ConnectionProviderBuilder. package br.edu.utfpr.application; import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.service.jdbc.connections.internal   .DriverManagerConnectionProviderImpl;

//Classe responsável por prover conexão com o banco de dados a partir de //configurações e propriedades

public class ConnectionProviderBuilder {

//Constantes utilizadas para configuração da conexão com a base de dados. public static final String DRIVER = "com.mysql.jdbc.Driver";

//Para este exemplo assumiu-se o esquema “cliente1” como default. public static final String URL =

"jdbc:mysql://localhost:3306/cliente1"; public static final String USER = "user"; public static final String PASS = "password";

public static Properties getConnectionProviderProperties (String dbName) {

Properties props = new Properties(null); props.put(Environment.DRIVER, DRIVER);

props.put(Environment.URL, String.format(URL, dbName)); props.put(Environment.USER, USER);

props.put(Environment.PASS, PASS); return props;

}

private static DriverManagerConnectionProviderImpl buildConnectionProvider(

Properties props, final boolean allowAggressiveRelease) { DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl() {

public boolean supportsAggressiveRelease() { return allowAggressiveRelease;

(17)

} };   connectionProvider.configure(props); return connectionProvider; } }

Concluída a implementação de ConnectionProviderBuilder, deve-se criar uma nova classe para que seja possível obter conexões baseadas em identificadores. Seu nome, acompanhado de sua localização no projeto, devem ser atribuídos à propriedade

hibernate.multi_tenant_connection_provider, definida no XML de configurações do Hibernate.

Esta nova classe, em nosso exemplo, receberá o nome de

MultiTenantConnectionProviderImpl, e será responsável por prover conexões de acordo com o identificador do inquilino, s endo esta uma das características ess enciais na implementação do modelo arquitetural Multi-Tenant. Para que isso seja po ss ível o

Hibernate fornece a interface MultiTenantConnectionProvider , que define uma série de métodos necessários para obtenção e liberação do acesso à fonte de dados e que devem ser implementados. Detalhes de sua implementação estão apresentados na Listagem 8. Listagem 8. Classe provedora de conexões baseadas em identificadores –

MultiTenantConnectionProviderImpl. package br.edu.utfpr.application; import java.sql.Connection; import java.sql.SQLException; import org.hibernate.HibernateException; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvi

//Classe responsável por prover conexões baseadas nos identificadores // dos clientes

public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {

//Definição da instância da classe construtora de provedores de conex private final ConnectionProvider connectionProvider =

ConnectionProviderBuilder

(18)

//Método que permite o acesso à base de dados em situações onde não há //identificadores para os clientes

  @Override

public Connection getAnyConnection() throws SQLException { return connectionProvider.getConnection();

}

//Método de libera uma conexão obtida através do método // getAnyConnection()

  @Override

public void releaseAnyConnection(Connection connection) throws SQLException {

  connectionProvider.closeConnection(connection); }

//Método que obtém uma conexão de acordo com o identificador do cliente //(esquema)

  @Override

public Connection getConnection(String tenantIdentifier) throws SQLException {

final Connection connection = getAnyConnection(); try {

connection.createStatement().execute("USE " +

  tenantIdentifier);

} catch (SQLException e) {

throw new HibernateException(

"Não pode alterar a conexão para o esquema especificado [" + tenantIdentifier + "]", e);

}

return connection; }

//Método que libera uma conexão obtida através do método // getConnection()

@Override

public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException { try { connection.createStatement().execute("USE " + tenantIdentifier); } catch (SQLException e) {

throw new HibernateException(

" Não pode alterar a conexão para o esquema especificado + tenantIdentifier + "]", e);

}

(19)

}

//Métodos não utilizados neste exemplo, mas que precisam ser sobrescritos.

  @Override

public boolean isUnwrappableAs(@SuppressWarnings("rawtypes") Class arg0) {…

@Override

public <T> T unwrap(Class<T> arg0) {…

@Override

public boolean supportsAggressiveRelease() {…

}

Para finalizar, propõ e-se a criação de uma classe para inserir alguns registros na base de dados , apenas para demonstrar o us o da funcionalidade de Multi-Tenancy. A

implementação desta visa obter sess ões de acordo com o inquilino desejado e realizar inserções utilizando a sessão adquirida. A Listagem 9 apresenta o código dessa classe. Um detalhe importante nesta class e é a definição do método

configureSessionFactory(), que segue o novo modelo definido pelo Hibernate para obtenção de uma SessionFactory. Seu funcionamento baseia-s e essencialmente na utilização do arquivo XML de propriedades para configurar novas fábricas de sessão. Listagem 9. Código da classe de testes MultiTenancyEsquemaExclusivo.

package br.edu.utfpr.application; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import br.edu.utfpr.modelo.Pessoa;

public class MultiTenancyEsquemaExclusivo {

// Fábrica de sessões

(20)

public static void main(String[] args) {

sessionFactory = configureSessionFactory();

//Obtenção de sessão através do identificador do cliente1 Session session = sessionFactory.withOptions()

  .tenantIdentifier("cliente1").openSession();

session.beginTransaction(); Pessoa pessoa = new Pessoa();

  pessoa.setId(1L);

pessoa.setNome("Tenant One");   session.save(pessoa);

  session.getTransaction().commit(); //Encerrando sessão do cliente1 session.close();

//Obtenção de sessão através do identificador do cliente2

session = sessionFactory.withOptions().tenantIdentifier("cliente2")

  .openSession();

session.beginTransaction(); Pessoa pessoa2 = new Pessoa();   pessoa2.setId(1L);

pessoa2.setNome("Tenant Two");   session.save(pessoa2);

  session.getTransaction().commit(); //Encerrando sessão do cliente2

  session.close();

}

// Método que realiza as configurações da fábrica de sessões private static SessionFactory configureSessionFactory()

throws HibernateException {

Configuration configuration = new Configuration().configure(); ServiceRegistryBuilder serviceRegistryBuilder = new ServiceRegistryBuilder();   serviceRegistryBuilder.applySettings   (configuration.getProperties()); ServiceRegistry serviceRegistry = serviceRegistryBuilder.buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory   (serviceRegistry); return sessionFactory; }

(21)

}

A Listagem 10 apresenta o resultado obtido após a execução da classe de testes MultiTenancyEsquemaExclusivo. Esse resultado demonstra que o processo de

inserção s eguiu a definição do cliente, conforme os parâmetros utilizados na obtenção de novas sess ões, e que os dados foram armazenados de acordo com a separação po r

esquema.

Listagem 10. Resultado da execução da aplicação.

Mar 10, 2013 3:53:07 AM org.hibernate.tool.hbm2ddl.SchemaExport execute INFO: HHH000230: Schema export complete

  Hibernate: insert into   Pessoa (nome, id) values (?, ?)  Hibernate: insert into   Pessoa (nome, id) values (?, ?)

A Listagem 11 apresenta duas consultas feitas nas tabelas para checar os resultados das inserções. Como pode ser visto a partir dos registros retornados, as ações de inserção foram bem sucedidas.

Listagem 11. Resultado das consultas realizadas nas tabelas de cada cliente.

mysql> USE cliente1;

mysql> SELECT * FROM Pessoa;

+----+---+ | id | nome |   +----+---+ | 1 + Tenant One |

(22)

  +----+---+

mysql> USE cliente2;

mysql> SELECT * FROM Pessoa;

+----+---+ | id | nome |   +----+---+ | 1 + Tenant Two |   +----+---+

Conclusão

Este artigo apresentou as opções de suporte que o framework Hibernate, na versão 4, oferece ao modelo arquitetural Multi-Tenant. Foram descritas algumas das características presentes na nova versão da ferramenta e um dos recursos adicionados foi trabalhado em um exemplo prático.

Além de expor variações do modelo Multi-Tenant, foi construída uma aplicação a fim de exemplificar a atuação do framework sobre uma destas alternativas. O modelo escolhido define que cada cliente possui um esquema exclusivo em uma base de dados

compartilhada.

O exemplo abordado serve para compreender e aplicar a solução em um dos pos síveis modelos de arquitetura, porém, cabe ao arquiteto do sistema optar pela opção que melhor se ajusta às necessidades do projeto, levando em consideração os fatores positivos e negativos relacionados à sua adoção.

Dentre as principais vantagens ass ociadas ao emprego de uma solução Multi-Tenant, destacam-se a significativa redução de custos com recursos físicos, devido ao

compartilhamento e reutilização de infraestrutura de hardware, e a integridade dos dados dos diversos clientes, garantida pelo isolamento que os modelos proporcionam.

Em contrapartida, podem ser cons iderados aspectos negativos: a dificuldade de calcular os recursos necessários para cada novo cliente, garantindo que os demais inquilinos não sofram influência negativa desta inclusão, e o risco associado a uma possível falha nos recursos de uso compartilhado, que pode acabar afetando vários clientes e ocasionar uma perda de grandes volumes de dados.

(23)

Links

Hibernate – Community Documentation – Multi-Tenancy

http://docs.jboss.org/hibernate/core/4.1/devguide/en-US/html/ch16.html 

Hibernate 4: multitenancy, extensões, OSGI e uma entrevista com o líder do projeto

http://www.infoq.com/br/news/2012/01/hibernate-4 Multi-Tenant Data Architecture

http://msdn.microsoft.com /en-us/library/aa479086.aspx 

Using Hibernate to Implement Multi-Tenant Cloud Architecture http://www.devx.com/Java/Article/47817/0/page/2

What is Hibernate

http://onjava.com/pub/a/onjava/2005/09/21/what-is-hibernate.html  Hibernate JavaDoc 4.1

http://docs.jboss.org/hibernate/orm/4.1/javadocs/  Hibernate – JBoss Community

http://www.hibernate.org

DevMedia - Equipe De Moderação

 A DevMedia é um portal para analistas, desenvolvedores de sistemas, gerentes e DBAs com milhares de artigos, dicas, cursos e videoaulas gratuitos e exclusivos para assinantes.

Referências

Documentos relacionados

Os interessados em adquirir quaisquer dos animais inscritos nos páreos de claiming deverão comparecer à sala da Diretoria Geral de Turfe, localizada no 4º andar da Arquibancada

Após a queima, para os corpos com a presença do sienito observou-se que os valores de densidade diminuíram (comparados às respectivas densidades a seco), já

No entanto, maiores lucros com publicidade e um crescimento no uso da plataforma em smartphones e tablets não serão suficientes para o mercado se a maior rede social do mundo

O valor da reputação dos pseudônimos é igual a 0,8 devido aos fal- sos positivos do mecanismo auxiliar, que acabam por fazer com que a reputação mesmo dos usuários que enviam

Brasil Seguros e Previdência S/A), apresentou os trabalhos da Comissão de Inteligência de Mercado – CIM em 2017, que foram divididos em três projetos: 1) Insurtechs e

Detectadas as baixas condições socioeconômicas e sanitárias do Município de Cuité, bem como a carência de informação por parte da população de como prevenir

O número de desalentados no 4° trimestre de 2020, pessoas que desistiram de procurar emprego por não acreditarem que vão encontrar uma vaga, alcançou 5,8 milhões

Considera-se que a interdisciplinaridade contribui para uma visão mais ampla do fenômeno a ser pesquisado. Esse diálogo entre diferentes áreas do conhecimento sobre