Configurando dinamicamento o hibernate.cfg.xml

Pessoal,

Eu tenho uma aplicação que pode conectar na base de dados do servidor ou na base de dados do cliente, esta seleção é feita na tela de login logo após startar a aplicação. A minha pergunta é posso alterar a minha configuração dentro do XML(hibernate.cfg.xml)?

Segue a minha classe de conexão:

public class ConexaoHibernate {

	private static SessionFactory sessionFactory;
	@SuppressWarnings("unchecked")
	private static final ThreadLocal threadlocal = new ThreadLocal();
	static{
			try{
				sessionFactory = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
			}catch (Throwable e) {
				throw new ExceptionInInitializerError(e);
			}
	}
	@SuppressWarnings("unchecked")
	public static Session getInstance(){
		if(sessionFactory == null || sessionFactory.isClosed()) {
			   sessionFactory = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
		}
		Session session = (Session) threadlocal.get();
		session = sessionFactory.openSession();
		threadlocal.set(session);
		return session;
	}
}

Desde já agradeço a ajuda!

BMuniz, isso não é possível ser feito!

Os arquivos xml sobem junto com a aplicação e qualquer alteração feita nele não terá efeito na sua aplicação, só terá após o servidor ser restartado.

Caro Kanin,

Existe alguma alternativa? Sei lá, trocar do XML para o properties… colocar alguma anotação…

Você pode criar uma Servlet para reinicializar o contexto toda vez que o arquivo sofrer alterações.

Kanin,

Cara, se não for pedir demais, posta ai, uma idéia de como se faz, só para eu me nortear, depois deixa comigo.

[]'s

[quote=BMuniz]Kanin,

Cara, se não for pedir demais, posta ai, uma idéia de como se faz, só para eu me nortear, depois deixa comigo.

[]'s[/quote]

Então creio que uma alternativa como essa pode ser valida.

Procura por WebApplicationContext do Spring, creio que irá te ajudar.

OK !

Tem como se fazer a configuração do session factory programaticamente.

Você usa Spring? Ou somente o Hibernate?
A aplicação está no servidor? Como saberá as informações do banco de dados local do cliente?

Rafael,

Não estou usando Spring, só o hibernate.

A aplicação será colocada no servidor que estará dentro da rede da empresa, ao abrir a aplicação na tela de login, seleciono a opção de servidor ou cliente, se seleciono cliente coloco o IP ou nome da máquina e me logo no BD da aplicação local do cliente, sendo esta aplicação desktop standlone.

Bom dia BMuniz,

Você tem duas alternativas para fazer estas conexões:

  1. Você criar 2 arquivos xml (o nome não precisa ser exatamente “hibernate.cfg.xml”), com isso, hora você utiliza um arquivo de conexão, hora você utiliza outro arquivo de conexão.

  2. Você pode configurar a sua conexão no código. Ex.:

Configuration conf = new AnnotationConfiguration().configure();
conf.setProperty("hibernate.connection.url", "jdbc:mysql://" + server + ":" + port + "/" + db);
conf.setProperty("hibernate.connection.username", user);
conf.setProperty("hibernate.connection.password", password);
sessionFactory = conf.buildSessionFactory();

Espero ter ajudado…

Até mais

mrsuzuki,

Eu fiz como você me disse, mas, como posso definir o banco em tempo de execução se a SessionFactory pede uma variável estática?

Em relação ao cfg.xml, eu não consigo colocar o valor da variável dentro do xml no tempo de execução.

Vou colocar o meu código abaixo para ver se o que estou fazendo é o que você está entendendo.


public class ConexaoHibernate {
	
	private static String url = new UsuarioControler().getIpnomemaquinacliente();
	 									
	private static SessionFactory sessionFactory;
	
	
	@SuppressWarnings("unchecked")
	private static final ThreadLocal threadlocal = new ThreadLocal();
	static{
    			try{
    					sessionFactory =  ((AnnotationConfiguration) new AnnotationConfiguration()
											.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")
											.setProperty("hibernate.connection.password","senha")
											.setProperty("hibernate.connection.url", url)
											.setProperty("hibernate.connection.username","usuario")
											.setProperty("hibernate.show_sql", "true")
											.setProperty("hibernate.format_sql", "true")
											.setProperty("hibernate.cache.use_query_cache", "true")
											.setProperty("hibernate.cache.use_second_level_cache", "true")
											.setProperty("hibernate.connection.autocommit", "true"))
											.addAnnotatedClass(Classe.class)
											.addAnnotatedClass(Classea.class)
											.configure()
											.buildSessionFactory();

    			}catch (Throwable e) {
    				throw new ExceptionInInitializerError(e);
    			}
	}
	@SuppressWarnings("unchecked")
	public static Session getInstance(){
		if(sessionFactory == null || sessionFactory.isClosed()) {
				sessionFactory =  ((AnnotationConfiguration) new AnnotationConfiguration()
									.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")
									.setProperty("hibernate.connection.password","senha")
									.setProperty("hibernate.connection.url", url)
									.setProperty("hibernate.connection.username","usuario")									
									.setProperty("hibernate.show_sql", "true")
									.setProperty("hibernate.format_sql", "true")
									.setProperty("hibernate.cache.use_query_cache", "true")
									.setProperty("hibernate.cache.use_second_level_cache", "true")
									.setProperty("hibernate.connection.autocommit", "true"))
									.addAnnotatedClass(Classe.class)
									.addAnnotatedClass(Classea.class)
									.configure()
									.buildSessionFactory();
		}
		Session session = (Session) threadlocal.get();
		session = sessionFactory.openSession();
		threadlocal.set(session);
		return session;
	}
}

Olá BMuniz,

Se preferir, você pode configurar dinamicamente somente algumas partes do arquivo “hibernate.cfg.xml”.
Fiz um exemplinho rápido. Criei 2 bancos iguais, somente para testar, com 2 tabelas, pessoa e dependente.
Primeiro eu acesso o banco javatest, fecho a conexão, e depois acesso o banco javatest2.
Dá uma olhada no exemplo que fiz…

Arqvuivo hibernate.cfg.xml (não contém nome do servidor, nome do banco, nem login e nem senha, tudo configurado dinamicamente)

<hibernate-configuration> 
	<session-factory>

		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

		<property name="hibernate.show_sql">false</property>
		<property name="hibernate.format_sql">false</property>
		
		<property name="hibernate.c3p0.min_size">5</property>
		<property name="hibernate.c3p0.max_size">20</property>
		<property name="hibernate.c3p0.timeout">180</property>
		<property name="hibernate.c3p0.idle_test_period">100</property>

        <mapping class="br.com.teste.entity.Pessoa"/>
        <mapping class="br.com.teste.entity.Dependente"/>
		
	</session-factory>
</hibernate-configuration>

HibernateUtil

public class HibernateUtil {
	   
	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
	private static SessionFactory sessionFactory = null;
   

	public static Session openSession(String servidor, String base, String login, String senha) {
		
        Configuration config = new AnnotationConfiguration().configure("hibernate.cfg.xml");
        config.setProperty("hibernate.connection.url", "jdbc:mysql://" + servidor + ":3306/" + base);
        config.setProperty("hibernate.connection.username", login);
        config.setProperty("hibernate.connection.password", senha);
		sessionFactory =  config.buildSessionFactory();
		threadLocal.set(sessionFactory.openSession());
		return threadLocal.get();
		
	}
	
	public static void closeCurrentSession() {
		threadLocal.get().close();
		threadLocal.set(null);
	}

	public static Session getCurrentSession() {
		return threadLocal.get();
	}
   
}

Main do programa

public static void main(String[] args) {
		
    Session session = HibernateUtil.openSession("localhost", "javatest", "marcelo", "suzuki");
    List<Pessoa> pessoaList = session.createCriteria(Pessoa.class).list();
    for (Pessoa pessoa : pessoaList) {
        System.out.println(pessoa.getNome());
    }
    HibernateUtil.closeCurrentSession();
		
    session = HibernateUtil.openSession("localhost", "javatest2", "marcelo", "suzuki");
    pessoaList = session.createCriteria(Pessoa.class).list();
    for (Pessoa pessoa : pessoaList) {
        System.out.println(pessoa.getNome());
    }
    HibernateUtil.closeCurrentSession();
}