Não funciona: Spring + JPA (Hibernate+C3PO) com multiplos DataSources

4 respostas
C

Olá,

Estou desenvolvendo uma aplicação de integração que terá 3 bancos conectados, um deles será o provedor de informações ou seja, todas as ações estão neste banco, e dependo da informação será gravado ou no banco1 ou no banco2, ou em alguns casos somente será efetuado uma consulta e retornado ao banco1.

Baseado em alguns exemplos gerei os códigos abaixo que aparentemente estão rodando, porém não estão gravando nada, e ainda esta reconectando a cada vez que a thread é executada.

/*Main.java*/
package br.com.cmnp.migra;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import br.com.cmnp.migra.manager.MigracaoManager;

public class Main extends Thread{

    EntityManagerFactory factory1 = Persistence.createEntityManagerFactory("pu1");
    EntityManager em1 = factory1.createEntityManager();			
	    
	public Main() throws InterruptedException {		
		
		MigracaoManager migracaoManager = new MigracaoManager();
		migracaoManager.migraDados(em1);
		
	}
	
	public static void main(String[] args) throws InterruptedException {
		int retorno = 0;
		while (retorno == 0) {
			Thread tmain = new Main();
			tmain.start();
			Thread.sleep(2000);
		}
	}

}
/*MigracaoManager.java*/
package br.com.cmnp.migra.manager;

import static com.google.code.liquidform.LiquidForm.alias;
import static com.google.code.liquidform.LiquidForm.select;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;

import br.com.cmnp.migra.persistence.entity.Tabela1;
import br.com.cmnp.migra.persistence.entity.Tabela2;
import br.com.cmnp.migra.persistence.entity.Tabela3;

public class MigracaoManager  {
	
    
    EntityManagerFactory factory2 = Persistence.createEntityManagerFactory("pu2");
    EntityManager em2 = factory2.createEntityManager();

    EntityManagerFactory factory3 = Persistence.createEntityManagerFactory("pu3");
    EntityManager em3 = factory3.createEntityManager();
    
	
	public void migraDados(EntityManager em1) {
		System.out.println("Vai começar...");
		
		Tabela1 t = alias(Tabela1.class, "t");
		String query = select(t).from(Tabela1.class).as(t).toString();
		try{
			
			List<Tabela1> resultList = em1.createQuery(query).getResultList();
			for (Tabela1 t1 : resultList) {
				System.out.println("Lendo..."+t1.getNome());
				t1.setStatus("Atualizando");
				em1.merge(t1);
				
				switch (t1.getDestino()) {
				case 2:
					Tabela2 t2 = new Tabela2();
					t2.setNome(t1.getNome());
					em2.persist(t2);
					t1.setStatus("Atualizado");
					break;

				case 3:
					Tabela3 t3 = new Tabela3();
					t3.setNome(t1.getNome());
					em3.persist(t3);
					t1.setStatus("Atualizado");
					break;
					
				default:
					t1.setStatus("Destino invalido");
					break;
				}
				
				em1.merge(t1);
				System.out.println(t1.getNome()+ "..."+t1.getStatus());
			}

		}
		catch(PersistenceException pe){
			System.out.println("PException:"+pe.getMessage());
		}		
		catch(Exception e){
			System.out.println("Exception:"+e.getMessage());
			
		}
		
		em2.close();
		em3.close();
		
	}

}
/*Tabela1.java*/
package br.com.cmnp.migra.persistence.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Tabela1 implements Serializable {
	
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Long id;
	
	private String nome;
	private String status;
	private int destino;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getStatus() {
		return status;
	}

	public void setDestino(int destino) {
		this.destino = destino;
	}

	public int getDestino() {
		return destino;
	}

}

A Tabela2 e Tabela3 são iguais:

/*Tabela3.java*/
package br.com.cmnp.migra.persistence.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Tabela3 implements Serializable {
	
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Long id;
	
	private String nome;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

}

e o persistence.xml:

<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_1_0.xsd"
  version="1.0">
  <persistence-unit name="pu1" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
	<class>br.com.cmnp.migra.persistence.entity.Tabela1</class>
	<exclude-unlisted-classes />
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="update"/>

      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
      <property name="hibernate.connection.url" value="jdbc:mysql://localhost/c1"/>
      <property name="hibernate.connection.username" value="c1"/>
      <property name="hibernate.connection.password" value="c1"/>

      <property name="hibernate.c3p0.min_size" value="5"/>
      <property name="hibernate.c3p0.max_size" value="20"/>
      <property name="hibernate.c3p0.timeout" value="300"/>
      <property name="hibernate.c3p0.max_statements" value="50"/>
      <property name="hibernate.c3p0.idle_test_period" value="3000"/>

    </properties>
  </persistence-unit>
  <persistence-unit name="pu2" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
	<class>br.com.cmnp.migra.persistence.entity.Tabela2</class>
	<exclude-unlisted-classes />
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="update"/>

      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
      <property name="hibernate.connection.url" value="jdbc:mysql://localhost/c2"/>
      <property name="hibernate.connection.username" value="c2"/>
      <property name="hibernate.connection.password" value="c2"/>

      <property name="hibernate.c3p0.min_size" value="5"/>
      <property name="hibernate.c3p0.max_size" value="20"/>
      <property name="hibernate.c3p0.timeout" value="300"/>
      <property name="hibernate.c3p0.max_statements" value="50"/>
      <property name="hibernate.c3p0.idle_test_period" value="3000"/>

    </properties>
  </persistence-unit>  
  <persistence-unit name="pu3" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
	<class>br.com.cmnp.migra.persistence.entity.Tabela3</class>
	<exclude-unlisted-classes />
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="update"/>

      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
      <property name="hibernate.connection.url" value="jdbc:mysql://localhost/c3"/>
      <property name="hibernate.connection.username" value="c3"/>
      <property name="hibernate.connection.password" value="c3"/>

      <property name="hibernate.c3p0.min_size" value="5"/>
      <property name="hibernate.c3p0.max_size" value="20"/>
      <property name="hibernate.c3p0.timeout" value="300"/>
      <property name="hibernate.c3p0.max_statements" value="50"/>
      <property name="hibernate.c3p0.idle_test_period" value="3000"/>

    </properties>
  </persistence-unit>  
</persistence>

Sei que ficou extenso, mas como são várias itens a serem melhorados/verificados, se pudessem me ajudar no porque não esta gravando (continuo testando aqui), como fazer para criar uma thread no primeiro banco que fique conectado sempre lendo a tabela1, e quando necessário conecta nos demais bancos e desconecte após a ação.

Se acharem necessário mais alguma informação, pois não gerou nenhum erro durante a execução.

Obrigado pela ajuda.

4 Respostas

jyoshiriro

Amigo, não vi você inicando nem “comitando” nenhuma transação.

Exemplo para 1 EntityManager:

em.getTransaction().begin(); // faz a(s) operação(ões) em.getTransaction().commit();

C

Obrigado,

Realmente, como quando conheci utilizei outros modelos, não prestei atenção neste problema, simples, mas importante. obrigado.

Comecei tentando implementar a injeção de dependências através da anotação @PersistenceContext evitando controlar os objetos que ao invés de utilizar:

EntityManagerFactory factory1 = Persistence.createEntityManagerFactory("pu1");  
    EntityManager em1 = factory1.createEntityManager();

passaria a utilizar:

@PersistenceContext (unitName = "pu1")
EntityManager em1;

Porém não consegui entender como implementar as configurações (beans) para mais de um datasource e nem muito bem a real diferença entre as duas implementações.

E em relação a thread, este é melhor jeito para forçar meu programa a sempre executar determinar rotina, que neste caso será a leitura da tabela1.

Obrigado por enquanto pessoal.

Cleilton

jyoshiriro

Amigo, a anotação

só funciona em EJBs (Session Beans). Não me parece que estas usando isso.

C

jyoshiriro me desculpe, (ainda estou pesquisando) mas na prática o que seria a diferença implementando o Session Beans.

Meu sistema, teria uma base sempre conectada e sendo lida de segundo em segundo, e conforme as informações lidas irei conectar nas outras base ou também poderia mantê-las conectadas e simplesmente executar a ação.

Se eu efetuar todas as conexões no meu Main, depois tem como recuperar esta conexão nas outras classes, ou eu sempre deverei passar minha EntityManager como parâmetro para as outras classes.

Se minhas perguntas estiverem muito básicas e puder me indicar um linha de estudo para esta aplicação.

Obrigado.

Criado 30 de dezembro de 2009
Ultima resposta 5 de jan. de 2010
Respostas 4
Participantes 2